Binding datagrid column width
Asked Answered
C

3

13

I have two datagrids with one column each. First:

<DataGrid.Columns>
   <DataGridTextColumn x:Name="FilterTextCol01" 
                       IsReadOnly="False" 
                       Width="{Binding ElementName=TextCol01, Path=ActualWidth, Mode=TwoWay}" />
</DataGrid.Columns>

Second:

<DataGridTextColumn CellStyle="{StaticResource DataGridColumnContentLeft}"
                    local:DataGridUtil.Name="TextCol01"
                    x:Name="TextCol01"
                    Header="TextCol01"
                    SortMemberPath="TextCol01"
                    Binding="{Binding TextCol01}" 
                    Width="Auto" 
                    IsReadOnly="True"/>

Binding of the width of first column to the width of the second doesn't work. If I'm doing it in code that way:

FilterTextCol01.Width = TextCol01.ActualWidth;

It works. Could anyone tell me why the first approach doesn't work?

Contumelious answered 16/2, 2012 at 15:3 Comment(0)
L
22

Because DataGrid columns are abstract objects which do not appear in the logical or visual tree of your window. You cannot bind properties on them using ElementName (there will be no namescope which is needed for those bindings).

You can try using Source and x:Reference instead, e.g.

{Binding Source={x:Reference TextCol01}, Path=ActualWidth}
Leonteen answered 16/2, 2012 at 15:31 Comment(9)
Can there be a TwoWay binding from read-only property ActualWidth?Abstergent
@H.B. great. Thanks it works. I never would have guessed it. How long does one need to know such deep buried things?Contumelious
@manton: Don't know, depends on when you stumble upon them, there are a lot of details in WPF which one may come across sooner or later, sometimes even after one or more years i suppose.Leonteen
@manton: By the way, you might be interested in methods to debug bindings and you should probably start to accept answers if they answer your question.Leonteen
@H.B. But unexpectedly there is another problem with your solution: "Service provider is missing the INameResolver service" the part "x:Reference TextCol01" is underlined as error. Do you have any clue on what it might be?Contumelious
@manton: You're using the designer i suppose? I would suggest you ignore the error as it is created by the designer as far as i know.Leonteen
@H.B. Thank you! You cannot imagine how frustrating this has been. Literally never seen x:Reference before!Tunisia
@H.B. Is there any chance you know the <Binding ... /> syntax of this answer for MultiBinding? I could use it for my question: Bind DataGrid Column Width to Two Colums of Another DataGrid.Kneedeep
@Steven: Should simply be <Binding Source="{x:Reference ...}" Path="ActualWidth"/>Leonteen
P
2

As H.B. said this property isn't in logical or visual tree.

Also have a look at this approach based on a binding proxy.

SourceCode

<DataGrid ItemsSource="{Binding Lines}" AutoGenerateColumns="False" >
    <DataGrid.Resources>
        <local:BindingProxy x:Key="proxy" Data="{Binding}"/>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Header="ProductId1" Binding="{Binding Path=Result[0]}" Width="{Binding Data.Columns[0].Width, Source={StaticResource proxy}, Mode=TwoWay}" />
        <DataGridTextColumn Header="ProductId2" Binding="{Binding Path=Result[1]}" Width="{Binding Data.Columns[1].Width, Source={StaticResource proxy}, Mode=TwoWay}"/>
    </DataGrid.Columns>
</DataGrid>

class BindingProxy : Freezable
{
    //Override of Freezable
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }
    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }
    public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}


public class Column : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;
    protected internal void OnPropertyChanged(string propertyname)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
    }

    public DataGridLength Width
    {
        get { return m_width; }
        set { m_width = value; OnPropertyChanged("Width"); }
    }
    DataGridLength m_width;
}

Also see https://mcmap.net/q/904886/-datagridcolumn-binding-visibility-and-width-via-bindingproxy-show-different-behavior

Plantaineater answered 17/10, 2017 at 11:23 Comment(0)
P
0

I've been searching for something like this. I found a solution so i'm posting it in order to help some other person with the same issue.

In my implementation i use a Custom DataTemplate for the Header of the DataGridTextColumn!!

So assigning Width="{Binding ActualWidth, RelativeSource={RelativeSource Mode=TemplatedParent}}" to the TextBlock used as DataGridColumnHeader i am able to set its Width to the DataGridTextColumn ActualWidth

Planography answered 8/7, 2015 at 9:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.