As the columns of a data grid aren't in the visual tree of datagrid I'm m using this approach of Binding Proxy to bind Visibility of a DataGridTextColumn
.
For some reason I would like to understand the same approach does work fine for Visibility
but not for column's Width
property.
Could someone explain this different behavior to me?
Code sample
c#
class BindingProxy : Freezable
{
#region Override of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion //Override of Freezable
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 Column(bool visible = true)
{
if (visible == true)
Visible = Visibility.Visible;
else
Visible = Visibility.Collapsed;
Width = 200;
}
public Visibility Visible
{
get { return m_visible; }
set { m_visible = value; OnPropertyChanged("Visible"); }
}
Visibility m_visible;
public double Width
{
get { return m_width; }
set { m_width = value; OnPropertyChanged("Width"); }
}
double m_width;
}
just to make it easier to reproduce
public partial class MainWindow : Window
{
public MainWindow()
{
Lines = new ObservableCollection<tableline>();
for (int i = 0; i< 5; i++)
Lines.Add(new tableline());
Columns = new List<Column>();
Columns.Add(new Column(true));
Columns.Add(new Column(false));
InitializeComponent();
DataContext = this;
}
public List<Column> Columns { get; set; }
public ObservableCollection<tableline>Lines { get; set; }
}
public class tableline
{
public tableline()
{
Result = new List<string>();
int colCount = 2;
for (int i = 0; i < colCount; i++)
{
Result.Add(i.ToString() + " some text");
}
}
public List<string> Result { get; set; }
}
xaml
<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]}" Visibility="{Binding Data.Columns[0].Visible, Source={StaticResource proxy}}" Width="{Binding Data.Columns[0].Width, Source={StaticResource proxy}}" />
<DataGridTextColumn Header="ProductId2" Binding="{Binding Path=Result[1]}" Visibility="{Binding Data.Columns[1].Visible, Source={StaticResource proxy}}" Width="{Binding Data.Columns[1].Width, Source={StaticResource proxy}}"/>
</DataGrid.Columns>
</DataGrid>
Just for you to know what my original goal is. I would like to set a width to auto for all columns, but with a "maximum" column width during drawing of datagrid. However, user should be possible to resize over this limit. That's why i can't use MaxColumnWidth
So I thought easiest way to realize this would be to read width for every column and set it to "maximum" value if it's bigger than limit.
The type of the Width
property of a DataGridColumn
is DataGridLength
and not double
.
Change type of your source property:
public DataGridLength Width
{
get { return m_width; }
set { m_width = value; OnPropertyChanged("Width"); }
}
DataGridLength m_width;
And the Mode
of the Binding
:
<DataGridTextColumn Header="ProductId1" Binding="{Binding Path=Result[1]}"
Visibility="{Binding Data.Columns[0].Visible, Source={StaticResource proxy}}"
Width="{Binding Data.Columns[0].Width, Source={StaticResource proxy}, Mode=TwoWay}" />