问题
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
.
https://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/
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.
回答1:
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}" />
来源:https://stackoverflow.com/questions/46787360/datagridcolumn-binding-visibility-and-width-via-bindingproxy-show-different-beh