1

I have been reading some tutorials on XAML but it does not help me. I have an empty application window and I need to create 30 TextBoxes in 3 rows.

Being used on the win forms, I thought I would figure it out - well, I did not. I cannot seem to find a way how to create them on certain coordinates.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
KhDonen
  • 289
  • 4
  • 13

4 Answers4

3

You first want to place a Canvas control on your screen, then you can populate it with TextBoxes placed at whatever Canvas.Left and Canvas.Top position you want.

That said though, WPF has a much better layout/arrangement system than WinForms, and trying to use it like it's WinForms means you'll miss out on a lot of what makes WPF so great, and you'll be making things a lot harder on yourself.

The WPF way of doing the same thing would be to use an ItemsControl, and a collection of objects that each contain data that the UI needs to to know for display purposes.

First you would create a class to represent each TextBox

public class MyClass
{
    public string Text { get; set; }
    public int X { get; set; }
    public int Y { get; set; }
}

Note: This class should implement INotifyPropertyChanged if you want to change the properties at runtime and have the UI automatically update.

Then make a list of this class, and bind it to an ItemsControl

<ItemsControl ItemsSource="{Binding ListOfMyClass}" />

Then you'd want to overwrite the ItemsPanelTemplate to be a Canvas (the best WPF panel for positioning items according to an X,Y position)

<ItemsControl ItemsSource="{Binding ListOfMyClass}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

Next overwrite the ItemTemplate to draw each item using a TextBlock

<!-- ItemTemplate -->
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <TextBox Text="{Binding Text}" />
    </DataTemplate>
</ItemsControl.ItemTemplate>

And add an ItemContainerStyle that binds Canvas.Left and Canvas.Top properties to X,Y properties on your object

<!-- ItemContainerStyle -->
<ItemsControl.ItemContainerStyle>
    <Style>
        <Setter Property="Canvas.Left" Value="{Binding X}" />
        <Setter Property="Canvas.Top" Value="{Binding Y}" />
    </Style>
</ItemsControl.ItemContainerStyle>

And this will take a List of MyClass objects, and render them to the screen inside a Canvas, with each item positioned at the specified X,Y coordinates.

With all that being said, are you sure this is what you want? WPF has much better layout panels than WinForms, and you don't have to position every element according to an X,Y coordinate if you don't want to.

For a quick visual introduction of WPF's Layouts, I'd recommend this link : WPF Layouts - A Visual Quick Start

Also since it sounds like you're new to WPF and coming from a WinForms background, you may find this answer to a related question useful : Transitioning from Windows Forms to WPF

Community
  • 1
  • 1
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • @PatrickHofman I used a Canvas because OP specified they want to set items at a specific X,Y coordinate, and the `Canvas` is the best control to do that with. I agree that for the grid-like layout being described, a different panel would most likely be best. Also, I changed the TextBlock to a Textbox, thanks :) – Rachel Jul 30 '14 at 13:38
  • @PatrickHofman Please don't ever use Margin for positioning in WPF lol :) The whole point of WPF's layouts is to make a consistent screen regardless of screen size or resolution, and positioning controls using Margin just defeats the point of that. The `Margin` property should be used to add a specific amount of whitespace around a control, and not for positioning a control – Rachel Jul 30 '14 at 13:43
  • 1
    @PatrickHofman Nope, but `Canvas.Left` is meant for positioning items at a specific X coordinate, unlike `Margin`. It's easy for other WPF developers to read, understand, and maintain your code. Also, I think it may matter for things like how a parent panel deals with a child that is positioned out of bounds, depending on what type of panel it is :) – Rachel Jul 30 '14 at 13:50
1

WPF layout involves choosing a layout container and placing your controls in it. There are several different containers:

  • The Grid container is a powerful tool for laying out your form in rows and columns. You have complete control over the size of each cell, and you can have rows or columns "span" each other.
  • The DockPanel container allows you to "dock" controls to the edges of your window or the center. You'd use it to layout a window with smart icon bars, ribbons, status windows, and toolboxes, like Visual Studio itself.
  • The StackPanel container can be used to stack controls either on top of each other or next to each other
  • The UniformGrid container is a less powerful version of the container that keeps all cells the same size.
  • The Canvas container allows you to specify the X & Y coordinates of your controls.

There are one or two others but these are the ones I've used.

The bad thing about laying out a form using X & Y coordinates is that the form does not handle resizing well. This can be exacerbated when you support globalization, as the labels and such for a string may be a lot longer in a foreign language. The best example off the top of my head is Spanish. A lot of English phrases, when translated to Spanish, are a lot longer.

The Grid container gives you the most control over layout. Columns can automatically size themselves to the longest string in the column, while the rest of the columns adjust themselves as necessary, again automatically. You don't have to write one line of code to get that effect; it's all there in the Grid control out of the box.

If you insist on laying out your form the Winforms way, use a Canvas. But you're not going to get the benefit of using the more advanced layout facilities in the other containers, especially the Grid control. I use that almost exclusively in my forms.

EDIT

Using layout controls other than Canvas means that you think about layout differently in WPF than in WinForms. You work at a higher conceptual level and leave the details about figuring out where on the screen a particular control will be displayed to WPF. You also don't have things like the WinForms Anchor property in WPF, which always seemed kind of a hack to me.

Tony Vitabile
  • 8,298
  • 15
  • 67
  • 123
0

If you want to position the TextBoxes in a grid-way, use Grid:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="50" />
        <ColumnDefinition Width="50" />
        <ColumnDefinition Width="50" />
        ...
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <TextBox Grid.Row="0" Grid.Column="0" />
    <TextBox Grid.Row="0" Grid.Column="1" />
    <TextBox Grid.Row="0" Grid.Column="2" />
    ...

    <TextBox Grid.Row="1" Grid.Column="0" />
    <TextBox Grid.Row="1" Grid.Column="1" />
    <TextBox Grid.Row="1" Grid.Column="2" />
    ...
</Grid>
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
0

The WPF was designed to offer a power and rich framework for designer which make it a different from the classic winforms. You can achieve what want by adding your TextBox control to a canvas and changing the attached property following is a full example illustrating this:

MainWindow

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Canvas Name="mainCanvas" Margin="31,-10,-31,10">
            <TextBox Name="myTextBox" Canvas.Left="131" Canvas.Top="109" Height="84" Width="135"></TextBox>
            <Button Content="Button" Height="62" Canvas.Left="271" Canvas.Top="69" Width="91" Click="Button_Click"/>
        </Canvas>
    </Grid>
</Window>

Code Behind

using System.Windows;
using System.Windows.Controls;

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
           myTextBox.SetValue(Canvas.LeftProperty,(double)myTextBox.GetValue(Canvas.LeftProperty)+50.0);
        }
    }
}
BRAHIM Kamel
  • 13,492
  • 1
  • 36
  • 47