3
votes

I am trying to bind the width of my columns within a DataGrid to an application settings property. I have this working when binding is set to OneWay mode however, I need the setting to be updated based on the width of the column when the app closes. When I change the binding mode to TwoWay, the binding breaks all together. My code is below, how can I go about achieving this?

enter image description here

Extension Class

Public Class SettingBindingExtension
    Inherits Binding

    Public Sub New()
        Initialize()
    End Sub

    Public Sub New(ByVal path As String)
        MyBase.New(path)
        Initialize()
    End Sub

    Private Sub Initialize()
        Me.Source = MySettings.[Default]

        'OneWay mode works for the initial grid load but any resizes are unsaved.
        Me.Mode = BindingMode.OneWay

        'using TwoWay mode below breaks the binding...
        'Me.Mode = BindingMode.TwoWay
    End Sub

End Class

xaml

xmlns:w="clr-namespace:Stack"

<DataGrid>
...
    <DataGridTextColumn Header="STACK" 
                        Width="{w:SettingBinding StackColumnWidth}"/>
...
</DataGrid>
3
Thanks for awesome solutionSerge P

3 Answers

1
votes

The problem is that Width is of type DataGridLength and there is no default converter back to double so you will need to create your own converter to do that, here is an example of converter which should work:

class LengthConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        DataGridLengthConverter converter=new DataGridLengthConverter();
        var res = converter.ConvertFrom(value);
        return res;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        DataGridLength length = (DataGridLength)value ;
        return length.DisplayValue;
    }
}
1
votes

Thanks for the responses, it was a datatype issue. Instead of using a converter, I just changed the datatype of the setting over to DataGridLength. Nothing else was changed and everything functions as it should. Thanks again.

enter image description here

0
votes

The DataGridTextColumn.Width property can definitely handle a Two Way Binding, so I can only assume that your custom Binding object is causing this problem. You said that the Binding broke, but you didn't tell us what the error was. As a simple test, try replacing it with the standard Binding class:

<DataGridTextColumn Header="STACK" Width="{Binding StackColumnWidth}" />

One other thing to note is that on the DataGridColumn.Width Property page at MSDN, it says:

The DisplayValue of the Width property is constrained by the following properties, if they are set, in order of precedence:

• DataGridColumn.MaxWidth

• DataGrid.MaxColumnWidth

• DataGridColumn.MinWidth

• DataGrid.MinColumnWidth

Therefore, you may need to make sure that these are set to appropriate values. However, this is not causing your problem.

If you still can't get any resolution, you can try manually saving the value as the application closes if you have a reference to the DataGrid control:

int index = dataGrid.Columns.Single(c => c.Header == "STACK").DisplayIndex;
double width = dataGrid.Columns[index].Width;