Home > Software design >  Newbie question: how to bind to a part of the Margin property
Newbie question: how to bind to a part of the Margin property

Time:11-05

I'm taking my first steps in WPF binding, and I would like to bind two visual components: a DataGrid and a Label, the latter to be put above the other (not in front of it, I mean).

This is what I currently have:

<DataGrid x:Name="dg_SomeTable" HorizontalAlignment="Left" Height="auto"
       Margin="10,26,0,0" VerticalAlignment="Stretch" Width="74"/>
<Label Content="SomeTable" HorizontalAlignment="Left" Margin="10,0,0,0"
       VerticalAlignment="Top" 
       Width="{Binding Path=ActualWidth, ElementName=dg_SomeTable}"/>

As you can see, the Label's width is bounded to the width of the DataGrid.
This is already useful, but I'd like to go a step further, and not only bind the width, but also the X-coordinate.

I believe that that X-coordinate is the first entry of the Margin property, but I can't simply bind to that whole property, because this would place my Label in front of my DataGrid.

I have already done some very naïve steps:

  • I tried working with Margin.x or Margin.X or ..., but that seems not to work.
  • I tried replacing Margin with Left but that seems not to exist and I'm out of inspiration.

Does anybody know the good way to bind the X-coordinate of one visual component to the X-coordinate of another visual component, when the definition of the X-coordinates are embedded in the Margin property?

Oh, I checked this similar question but this involves actual programming, and I'm wondering if there's a simple XAML solution for this seemingly basic question.

Edit after comment, asking for more information:

Generally my XAML looks as follows:

<TabControl ...
    <TabItem ...
        <Grid ...
            <DataGrid x:Name="dg_SomeTable" ... Margin=... />
            <Label Content="SomeTable" ... />

As proposed, this should be replaced by something like:

<TabControl ...
  <TabItem ...
    <Canvas ...
      <DataGrid x:Name="dg_SomeTable" Width="222" Canvas.Left="10" ...
      <Label Content="SomeTable"
             Canvas.Left="{Binding Path=Left, 
                           RelativeSource={RelativeSource FindAncestor, 
                                           AncestorType={x:Type Canvas}}}"
             Width="{Binding Path=ActualWidth,
                     ElementName=dg_Locations}"/>

I can already hear your reaction "Now you are referring to the left of the Canvas where it's located in, while you should refer to the Canvas.Left of the DataGrid".
Well, I tried these:

Canvas.Left="{Binding Path=Canvas.Left, ElementName=dg_SomeTable}"
Canvas.Left="{Binding Path=Left, ElementName=dg_SomeTable}"

None of them worked.

How can I refer to the Canvas.Left of the DataGrid?

CodePudding user response:

How can I refer to the Canvas.Left of the DataGrid?

Like this (note the parentheses around the attached property name):

Canvas.Left="{Binding Path=(Canvas.Left), ElementName=dg_SomeTable}"

CodePudding user response:

Use converter

Step1. Make Converter


    public class MarginConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (!(value is Thickness)) return new Thickness(0, 0, 0, 0);

            Thickness gridMargin = (Thickness)value;

            return new Thickness(gridMargin.Left, 0,0,0);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return parameter;
        }
    }

Step2. Add to resource

    <Window.Resources>
        <local:MarginConverter x:Key="MarginConverter"/>
    </Window.Resources>

Step3. Bind Margin with converter

<Label Content="SomeTable" HorizontalAlignment="Left" 
   VerticalAlignment="Top" 
   Width="{Binding Path=ActualWidth, ElementName=dg_SomeTable}"
   Margin="{Binding Margin, ElementName=dg_SomeTable, Converter= {StaticResource MarginConverter}}"/>

This converter get dg_SomeTable's Margin and return new Margin ( dg_table's Margin.Left, 0 , 0, 0 )

  • Related