views:

55

answers:

1

I'm not sure what I'm doing wrong, but I am attempting to align my user control with the ColumnWidth of my grid using DataBinding and DependencyProperties.

I have a GridView on my Form Page which contains a two instances of a user control (Address). The address usercontrol contains a textlabel "header" so that I can name the user control "Office Address" or "Mailing Address" etc and is formatted using it's own GridView. I added a DependencyProperty to the user control called "HeaderWidth" which is simply an Int32. The problem is that even with the bindings, things don't align. I'm not sure what I'm doing wrong.

AddressField.xaml:

<UserControl x:Class="AddressField" x:Name="PART_AddressFieldControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         >
 <StackPanel Orientation="Horizontal">
  <Grid x:Name="StandardView">
   <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
   </Grid.RowDefinitions>
   <Grid.ColumnDefinitions>
    <ColumnDefinition Width="{Binding ElementName=PART_AddressFieldControl, Path=HeaderWidth}" />
    <ColumnDefinition Width="1*" />
    <ColumnDefinition Width="Auto" />
    <!-- ETC REMOVED FOR COMPACTNESS -->
   </Grid.ColumnDefinitions>

   <TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Right" Text="{Binding ElementName=PART_AddressFieldControl, Path=Header}" />
   <TextBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="8" MinWidth="300" Text="{Binding Address1}" />
   <!-- ETC REMOVED FOR COMPACTNESS -->

  </Grid>
 </StackPanel>
</UserControl>

AddressField.cs

public partial class AddressField : UserControl
{
    static AddressField()
    {
        HeaderProperty = DependencyProperty.Register("Header", typeof(String), typeof(AddressField), new UIPropertyMetadata("Address:"));

        HeaderWidthProperty = DependencyProperty.Register("HeaderWidth", typeof(Int32), typeof(AddressField), new UIPropertyMetadata());

        ViewProperty = DependencyProperty.Register("View", typeof(AddressFieldView), typeof(AddressField), new UIPropertyMetadata(AddressFieldView.STANDARD));
    }

    public AddressField()
    {
        InitializeComponent();
    }

    public String Header
    {
        get { return (String)GetValue(HeaderProperty); }
        set { SetValue(HeaderProperty, value); }
    }
    public static readonly DependencyProperty HeaderProperty;

    public Int32 HeaderWidth
    {
        get { return (Int32)GetValue(HeaderWidthProperty); }
        set { SetValue(HeaderWidthProperty, value); }
    }
    public static readonly DependencyProperty HeaderWidthProperty;
}

RegistrationForm.xaml

<!-- ETC REMOVED FOR COMPACTNESS -->

<Grid.ColumnDefinitions>
 <ColumnDefinition Width="Auto" Name="FirstWidth" />
 <ColumnDefinition Width="Auto" />
 <!-- ... ETC ... -->
</Grid.ColumnDefinitions>

<vws:AddressField Grid.Row="1" Grid.Column="0" Grid.RowSpan="3" Grid.ColumnSpan="9" Header="Office Address:" DataContext="{Binding OfficeAddressVM}" HeaderWidth="{Binding ElementName=FirstWidth, Path=ActualWidth}" />
<vws:AddressField Grid.Row="4" Grid.Column="0" Grid.RowSpan="3" Grid.ColumnSpan="9" Header="Mailing Address:" DataContext="{Binding MailingAddressVM}" HeaderWidth="{Binding ElementName=FirstWidth, Path=ActualWidth}" />

Basically, I'm trying to align the textlabel of the usercontrol with the registrationform first column width.

EDIT: Oh, and just because I was curious: I put a debugging breakpoint and dug deep into the UI Tree and got to the AddressField's "Header" (TextBlock) and the ActualWidth is not 0.0 but 73.9 or something like that, yet the UI doesn't take this into account, it still is not visible because the width is 0.0.

+1  A: 

There are easier ways you know :)

Simply put Grid.IsSharedSizeScope="True" on the grid in your main window (not in the control), and SharedSizeGroup="someRandomName" on all the columns you wish to share width - in this case, only the column you've bound in the user control, i.e. replace the binding with SharedSizeGroup. That's it! Any columns with the same SharedSizeGroup value will now be the same size, which is the size of the largest of them.

Granted, it only works well with Auto sizing but it sounds like that's what you want.

For more information you can look here and here.

Edit: as to what you were doing wrong, I suspect that the outer grid column, being sized to Auto, but not having any contents of its own to size by (because all the controls were spanning multiple columns), took on a width of zero. The bindings then propagated to the user controls. There are a lot of complicated interactions there though, and I don't have the entire XAML to judge, so I might be wrong.

Alex Paven
Actually, I ended up changing the styling of my forms alltogether, so I guess this isn't an issue anymore. Though, I do suspect your answer probably would work. Also, after thinking about it, I suspect the problem is just that... that I was trying to bind to a user control from the parent grid, which would trigger a resize... something along those lines.
myermian
Yep, I did test it with the snippets you provided to make sure I don't misremember something, so it does work, and it's also a technique I've used before successfully. It's true though there are many ways to solve this problem :)
Alex Paven