如何拥有具有固定列的自定义数据网格控件,其宽度可调
本文关键字:控件 网格 数据网 数据 自定义 拥有 何拥有 | 更新日期: 2023-09-27 18:17:13
我要做的是使一个CustomDatagrid已经有2个固定列。然后我可以重用这个CustomDatagrid并添加额外的列来满足我的最佳目的。但是,当我添加额外的列,我希望能够调整2固定列。我试着用依赖属性作为下面的例子来解决它,但无济于事。我没有得到任何绑定错误,这让我不知道是什么错了。
=>这个小例子将阐明我要做什么
CustomDataGrid。Xaml
<DataGrid x:Class="DataGridWidthTestControl.CustomDataGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DataGridWidthTestControl"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<DataGrid.Columns>
<DataGridTextColumn Width="{Binding Column1Width}" Header="Column1"/>
<DataGridTextColumn Width="{Binding Column2Width}" Header="Column2"/>
</DataGrid.Columns>
CustomDataGrid.Xaml.CS - Codebehind
namespace DataGridWidthTestControl
{
/// <summary>
/// Interaction logic for CustomDataGrid.xaml
/// </summary>
public partial class CustomDataGrid : DataGrid
{
public CustomDataGrid()
{
InitializeComponent();
DataContext = this;
}
public static readonly DependencyProperty Column1WidthProperty = DependencyProperty.Register( "Column1Width", typeof(DataGridLength), typeof(CustomDataGrid), new FrameworkPropertyMetadata(new DataGridLength(25, DataGridLengthUnitType.Star)));
public DataGridLength Column1Width
{
get { return (DataGridLength)GetValue(Column1WidthProperty); }
set { SetValue(Column1WidthProperty, value); }
}
public static readonly DependencyProperty Column2WidthProperty = DependencyProperty.Register("Column2Width", typeof(DataGridLength), typeof(CustomDataGrid), new FrameworkPropertyMetadata(new DataGridLength(15, DataGridLengthUnitType.Star)));
public DataGridLength Column2Width
{
get { return (DataGridLength)GetValue(Column2WidthProperty); }
set { SetValue(Column2WidthProperty, value); }
}
}
}
主窗口。Xaml (codebehind为空,除了默认的初始化调用)
<Window x:Class="DataGridWidthTestControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataGridWidthTestControl"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:CustomDataGrid Column1Width="1*" Column2Width="1*" >
<DataGrid.Columns>
<DataGridTextColumn Width="10*" Header="column3"/>
</DataGrid.Columns>
</local:CustomDataGrid>
</Grid>
</Window>
您需要以编程方式在CustomDataGrid类中插入固定列,而不是在模板中指定它们。
类似:
public override void OnApplyTemplate()
{
if (!this.Columns.Any(c => c.Header.ToString() == "Column1"))
{
this.Columns.Insert(0,
new DataGridTextColumn
{
Width = this.Column1Width,
Header = "Column1"
});
}
if (!this.Columns.Any(c => c.Header.ToString() == "Column2"))
{
this.Columns.Insert(1,
new DataGridTextColumn
{
Width = this.Column2Width,
Header = "Column2"
});
}
base.OnApplyTemplate();
}
我不确定OnApplyTemplate()是正确的时间去做它,可能有一个更好的方法来覆盖,但这是我要去做这个工作的概念
首先,您需要知道没有指定任何源的绑定(就像您的情况一样),使用Binding.RelativeSource
的绑定和使用Binding.ElementName
的绑定将不能与DataGridColumn
一起工作,因为它直接派生自DependencyObject
,这是不够的。基本上,为了使这些工作,目标对象的类型需要派生自FrameworkElement
或FrameworkContentElement
,并且它应该是可视化或逻辑树的一部分(DataGridColumn
不是)。但是请注意,这个要求很少有例外(比如在资源字典中定义的Freezable
),并且在即将到来的框架版本中会有更多例外。
所以不幸的是你需要显式地指定Binding.Source
(这应该是你的CustomDataGrid
类的一个实例)。我想不出任何方法在XAML (Source={x:Reference (...)}
不适用,因为你不能从它的定义内引用对象),所以我认为你需要退回到代码隐藏(这在设计自定义控件时并不罕见)。
最简单的方法是命名您的列:
<DataGrid.Columns>
<DataGridTextColumn x:Name="Column1" x:FieldModifier="private" Header="Column1" />
<DataGridTextColumn x:Name="Column2" x:FieldModifier="private" Header="Column2" />
</DataGrid.Columns>
(x:FieldModifier="private"
是可选的),然后在控件初始化时设置绑定:
public CustomDataGrid()
{
InitializeComponent();
BindingOperations.SetBinding(Column1, DataGridColumn.WidthProperty, new Binding
{
Path = new PropertyPath(Column1WidthProperty),
Source = this,
});
BindingOperations.SetBinding(Column2, DataGridColumn.WidthProperty, new Binding
{
Path = new PropertyPath(Column2WidthProperty),
Source = this,
});
}
您还可以将Mode = BindingMode.TwoWay
添加到绑定中,以便在用户手动调整列大小时控件上的值保持同步。
请注意,我故意删除了DataContext = this
行,因为a)它不是必要的,b)它会给你很多麻烦,当使用你的控制(例如绑定DataGrid.ItemsSource
到一个视图模型属性将不工作,因为它通常做)。