如何在 WPF (MVVM) 中绑定数据网格列宽
How to bind datagrid columns width in WPF (MVVM)
我正在尝试绑定数据网格的列宽但不起作用。
<DataGridTextColumn Binding="{Binding Name}" Width="{Binding GridNameWidth}" Header="Name" />
后台代码如下:
public int GridNameWidth
{
get
{
return 300;
}
}
后端代码从未被触及。没有错误,但 name
字段具有默认宽度。我想让宽度绑定到我的 属性。我不需要双向绑定,只需要在加载网格时绑定宽度。这在 wpf 中可行吗?
如果您想让它起作用,您的 GridNameWidth 应该是 DataGridLength 类型。
DataGridTextColumn 是一个抽象对象,实际上并不是 VisualTree 的一部分,因此它不会像您对其他控件所期望的那样使用继承的 DataContext。
WPF 知道如何正确解析 Binding
属性 之类的内容并将绑定传输到每个 Cell,但是 Width 之类的内容只是按原样计算,并且无法正确计算,因为两者都不是DataContext 和 VisualTree 都按预期在那里。
一个常见的解决方案是改用静态数据源编写绑定。这是一个基于 this answer, which uses x:Reference 的示例,用于引用 XAML 标记中的另一个控件:
{Binding Source={x:Reference MyDataGrid}, Path=DataContext.NameColumnWidth}
或者,您可以使用控件定义自己的 DataGridCellTemplate
,该控件的宽度绑定到 DataItem属性 上的任何内容
如前所述,这里的问题是 DataGridTextColumn 不在逻辑树或可视树中。
另一种解决方案是这种基于提供绑定的绑定代理的方法。
源代码
<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;
}
对于此实现,直接在 DataContext 中使用 List<Column>
或 ObservableCollection,否则调整绑定。
我正在尝试绑定数据网格的列宽但不起作用。
<DataGridTextColumn Binding="{Binding Name}" Width="{Binding GridNameWidth}" Header="Name" />
后台代码如下:
public int GridNameWidth
{
get
{
return 300;
}
}
后端代码从未被触及。没有错误,但 name
字段具有默认宽度。我想让宽度绑定到我的 属性。我不需要双向绑定,只需要在加载网格时绑定宽度。这在 wpf 中可行吗?
如果您想让它起作用,您的 GridNameWidth 应该是 DataGridLength 类型。
DataGridTextColumn 是一个抽象对象,实际上并不是 VisualTree 的一部分,因此它不会像您对其他控件所期望的那样使用继承的 DataContext。
WPF 知道如何正确解析 Binding
属性 之类的内容并将绑定传输到每个 Cell,但是 Width 之类的内容只是按原样计算,并且无法正确计算,因为两者都不是DataContext 和 VisualTree 都按预期在那里。
一个常见的解决方案是改用静态数据源编写绑定。这是一个基于 this answer, which uses x:Reference 的示例,用于引用 XAML 标记中的另一个控件:
{Binding Source={x:Reference MyDataGrid}, Path=DataContext.NameColumnWidth}
或者,您可以使用控件定义自己的 DataGridCellTemplate
,该控件的宽度绑定到 DataItem属性 上的任何内容
如前所述,这里的问题是 DataGridTextColumn 不在逻辑树或可视树中。
另一种解决方案是这种基于提供绑定的绑定代理的方法。
源代码
<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;
}
对于此实现,直接在 DataContext 中使用 List<Column>
或 ObservableCollection,否则调整绑定。