Bob Tway
Bob Tway

Reputation: 9603

WPF DataGrid - Binding Source and Width to different objects

In my WPF application, I have a DataGrid which is bound to a collection in the viewmodel, but I want the width of the first column to be equal to a property on the viewmodel itself, like so:

public ObservableCollection<Booking> Bookings
{
    return repository.Bookings();
}

public int MaxWidth
{
    return 100;
}

(I realise there's no point in binding to a fixed property like this - it's for demo purposes)

<UserControl>
    <DataGrid DataContext="{Binding Bookings}">
        <DataGrid.Columns>
            <DataGridTextColumn Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.MaxWidth}" Header="Provider" Binding="{Binding Name}" />
        </DataGrid.Columns>
    </DataGrid>
</UserControl>

But if I do this, the width of the column remains at the default value - i.e. just wide enough to accommodate its value.

What am I doing wrong?

EDIT: Attempted this, to see what happened:

<Label Name="tricky" Content="500" Visibility="Collapsed"></Label>
...
<DataGridTextColumn Width="{Binding ElementName=tricky, Path=Content}" Header="Provider" Binding="{Binding Name}" />

Which did nothing. Is it not possible to set the width dynamically?

Upvotes: 1

Views: 1195

Answers (3)

user3455395
user3455395

Reputation: 161

MaxWidth and Bookings are siblings aren't they? So binding expressions for them should be identical.

Looking at your first XAML: Path=DataContext.MaxWidth - remove DataContext.
Looking at the second XAML: no need to specify Path twice, the first Path is enough, I'm not even sure if the actual construct is valid.

Generally, a lot of low level UI properties are POCOs rather than DPs, just make sure your target one is a DP.

Update - what you might want to do is to use FallbackValue = 900 as part of your binding expression, just to narrow the problem down - whether it's a binding problem or the target property isn't suitable for using as binding target.

Update 2 - most times you'll find yourself running out of steam rather quickly when going for that low level of managing your UI, it's often beneficial to create MVColum, managing headers, widths etc and create a behavior, which can apply all these settings in one go. Also that way you won't be dependent on a flavor of your target properties as you'll be setting them up right in your code.

Upvotes: 0

Chris
Chris

Reputation: 915

Alternatively a useful feature I use is as follow

IsEnabled="{Binding DataContext.IsEnabled,RelativeSource={RelativeSource AncestorType={x:Type Window}}}"  />

This allows you to link to properties outside of the itemssource of your grid.

Upvotes: 0

Rachel
Rachel

Reputation: 132558

I think the problem is the DataGridTextColum is not part of the Visual Tree (can verify with Snoop), so the binding never gets resolved.

The data obtained from the DataGridTextColumn is used to build the DataGridCell template, and at the time the template is built, the DataContext isn't set.

My suggestion would be to use a DataGridTemplateColumn, and specify your own CellTemplate that has the Width binding you need.

Upvotes: 2

Related Questions