Search code examples
c#wpfxamllayout

Do XAML controls have a center, which can be manipulated?


I have a XAML file, based on Grids, StackPanels, ...: on one row, I have a control, located on a StackPanel. Next to that there's another StackPanel. Next to that, there's a Grid, containing another StackPanel with two UserControls (UC1_1, UC1_2, UC2_1, UC2_2, ...), and so on, and so on, ...

Under that, I have another UserControl (OtherUC), and now I would like to do align that control on the other ones. In order to do that, I would need something like:

OtherUC.Margin.X = StackPanel1.Width + StackPanel1.Margin.X + 
                   StackPanel2.Width + StackPanel2.Margin.X + 
                   UC1_1.Width + UC1_1.Margin.X + 
                   UC1_2.Width + UC1_2.Margin.X + ...

It's possible that I don't need to add margins and widths, but that's not the point: the point is just that I need to add a lot of stuff for something, which could be so much easier as follows:

OtherUC.Center.X = UC1_4.Center.X;

Is that possible? Is there a Center property to a XAML control which can be set that easily?


Solution

  • There's no Center property that You can use.

    But I guess, if You'd like to center Controls based on other Controls positions, You can play with RenderTransfrom, either in XAML with binding, or in the Code Behind.

    For explanations sake, here's example in CodeBehind.

    Here's the minimal UI to reproduce the problem

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
    
        <Rectangle x:Name="rect1"
                   Width="10"
                   HorizontalAlignment="Left"
                   Fill="Red"/>
        <Rectangle x:Name="rect2"
                   Grid.Row="1"
                   Width="10"
                   HorizontalAlignment="Left"
                   Fill="Blue"/>
        <Rectangle x:Name="rect3"
                   Grid.Row="2"
                   Width="10"
                   HorizontalAlignment="Left"
                   Fill="Green"/>
    
        <StackPanel Grid.Row="3" Orientation="Horizontal">
            <Rectangle x:Name="stackRect1"
                       Width="50"
                       Margin="10"
                       Fill="Pink"/>
    
            <Rectangle x:Name="stackRect2"
                       Width="250"
                       Margin="10"
                       Fill="Pink"/>
    
            <Rectangle x:Name="stackRect3"
                       Width="278"
                       Margin="10"
                       Fill="Pink"/>
        </StackPanel>
    </Grid>
    

    and here's code behind

    public MainWindow()
    {
        InitializeComponent();
    
        this.Loaded += MainWindow_Loaded;
    }
    
    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        var a = stackRect1.TranslatePoint(new Point(stackRect1.Width / 2, 0), this);
        var b = stackRect2.TranslatePoint(new Point(stackRect2.Width / 2, 0), this);
        var c = stackRect3.TranslatePoint(new Point(stackRect3.Width / 2, 0), this);
    
        rect1.RenderTransform = new TranslateTransform(a.X, 0);
        rect2.RenderTransform = new TranslateTransform(b.X, 0);
        rect3.RenderTransform = new TranslateTransform(c.X, 0);
    }
    

    As You can see I use TranslatePoint to get centers of each 'Control', and then RenderTranform selected 'Control' to that center.