我要做的是创建一个已经有2个固定列的CustomDatagrid。然后我可以重新使用这个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); }
}
}
}
Mainwindow.xaml(除默认初始化调用外,代码隐藏为空)
<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>
答案 0 :(得分:2)
您需要以编程方式在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()是否是正确的时间,可能有更好的方法来覆盖,但这是我努力实现这一目标的概念。
答案 1 :(得分:1)
首先,你需要知道没有指定任何来源的绑定(如你的情况),使用white-space
的绑定和使用Binding.RelativeSource
的绑定不能用于Binding.ElementName
,因为它直接来自DataGridColumn
,这是不够的。基本上,为了使那些工作,目标对象需要是从DependencyObject
或FrameworkElement
派生的类型,它应该是视觉或逻辑树的一部分(FrameworkContentElement
s不是)。请注意,该要求的例外情况很少(例如资源字典中定义的DataGridColumn
),以及框架即将推出的版本会有更多例外。
很遗憾,您需要明确指定Freezable
(应该是您的Binding.Source
类的实例)。我无法想到在 XAML中做任何事情(CustomDataGrid
不适用,因为你无法在其定义中引用某个对象),所以我认为你&#39;我需要回退到代码隐藏(在设计自定义控件时这并不罕见)。
最简单的方法是命名列:
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
行,因为 a)没有必要和 b)在使用你时会给你带来很多麻烦控制(例如,绑定DataContext = this
到视图模型属性将不会像通常那样工作。)