使用绑定来控制 DataGrid 中的列顺序
问题
我有一个 WPF 工具包 DataGrid
,并且我希望能够在多个预设列顺序之间切换。这是一个 MVVM 项目,因此列顺序存储在 ViewModel
中。问题是,我无法让绑定适用于 DisplayIndex
属性。无论我尝试什么,包括 这个 Josh Smith 教程,我得到:
标题为“ID”的 DataGridColumn 的 DisplayIndex 超出范围。 DisplayIndex 必须大于或等于 0 且小于 Columns.Count。参数名称:显示索引。实际值为-1。
有解决方法吗?
我在下面添加了我的测试代码。如果您发现任何问题,请告诉我。
ViewModel 代码
public class MainViewModel
{
public List<Plan> Plans { get; set; }
public int IdDisplayIndex { get; set; }
public int NameDisplayIndex { get; set; }
public int DescriptionDisplayIndex { get; set; }
public MainViewModel()
{
Initialize();
}
private void Initialize()
{
IdDisplayIndex = 1;
NameDisplayIndex = 2;
DescriptionDisplayIndex = 0;
Plans = new List<Plan>
{
new Plan { Id = 1, Name = "Primary", Description = "Likely to work." },
new Plan { Id = 2, Name = "Plan B", Description = "Backup plan." },
new Plan { Id = 3, Name = "Plan C", Description = "Last resort." }
};
}
}
计划类
public class Plan
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
窗口代码 - 这使用 Josh Smith 的 DataContextSpy
<Window
x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:mwc="http://schemas.microsoft.com/wpf/2008/toolkit"
Title="Main Window" Height="300" Width="300">
<Grid>
<mwc:DataGrid ItemsSource="{Binding Plans}" AutoGenerateColumns="False">
<mwc:DataGrid.Resources>
<local:DataContextSpy x:Key="spy" />
</mwc:DataGrid.Resources>
<mwc:DataGrid.Columns>
<mwc:DataGridTextColumn
Header="ID"
Binding="{Binding Id}"
DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.IdDisplayIndex}" />
<mwc:DataGridTextColumn
Header="Name"
Binding="{Binding Name}"
DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.NameDisplayIndex}" />
<mwc:DataGridTextColumn
Header="Description"
Binding="{Binding Description}"
DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.DescriptionDisplayIndex}" />
</mwc:DataGrid.Columns>
</mwc:DataGrid>
</Grid>
</Window>
注意: 如果我只使用普通DisplayIndex
的数字,一切正常,因此问题肯定出在绑定上。
更新 5/1/2010
我只是对我的项目进行了一些维护,我注意到当我运行它时,我在这篇文章中讨论的问题又回来了。我知道上次运行它时它是有效的,因此我最终将问题范围缩小到我安装了较新版本的 WPF Toolkit(10 年 2 月)这一事实。当我恢复到 09 年 6 月版本时,一切又恢复正常了。因此,我现在正在做一些我应该首先做的事情:我将在我的解决方案文件夹中工作的 WPFToolkit.dll 包含在内,并将其签入版本控制中。但不幸的是,新的工具包发生了重大变化。
Problem
I have a WPF Toolkit DataGrid
, and I'd like to be able to switch among several preset column orders. This is an MVVM project, so the column orders are stored in a ViewModel
. The problem is, I can't get bindings to work for the DisplayIndex
property. No matter what I try, including the sweet method in this Josh Smith tutorial, I get:
The DisplayIndex for the DataGridColumn with Header 'ID' is out of range. DisplayIndex must be greater than or equal to 0 and less than Columns.Count. Parameter name: displayIndex. Actual value was -1.
Is there any workaround for this?
I'm including my test code below. Please let me know if you see any problems with it.
ViewModel code
public class MainViewModel
{
public List<Plan> Plans { get; set; }
public int IdDisplayIndex { get; set; }
public int NameDisplayIndex { get; set; }
public int DescriptionDisplayIndex { get; set; }
public MainViewModel()
{
Initialize();
}
private void Initialize()
{
IdDisplayIndex = 1;
NameDisplayIndex = 2;
DescriptionDisplayIndex = 0;
Plans = new List<Plan>
{
new Plan { Id = 1, Name = "Primary", Description = "Likely to work." },
new Plan { Id = 2, Name = "Plan B", Description = "Backup plan." },
new Plan { Id = 3, Name = "Plan C", Description = "Last resort." }
};
}
}
Plan Class
public class Plan
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Window code - this uses Josh Smith's DataContextSpy
<Window
x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:mwc="http://schemas.microsoft.com/wpf/2008/toolkit"
Title="Main Window" Height="300" Width="300">
<Grid>
<mwc:DataGrid ItemsSource="{Binding Plans}" AutoGenerateColumns="False">
<mwc:DataGrid.Resources>
<local:DataContextSpy x:Key="spy" />
</mwc:DataGrid.Resources>
<mwc:DataGrid.Columns>
<mwc:DataGridTextColumn
Header="ID"
Binding="{Binding Id}"
DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.IdDisplayIndex}" />
<mwc:DataGridTextColumn
Header="Name"
Binding="{Binding Name}"
DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.NameDisplayIndex}" />
<mwc:DataGridTextColumn
Header="Description"
Binding="{Binding Description}"
DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.DescriptionDisplayIndex}" />
</mwc:DataGrid.Columns>
</mwc:DataGrid>
</Grid>
</Window>
Note: If I just use plain numbers for DisplayIndex
, everything works fine, so the problem is definitely with the bindings.
Update 5/1/2010
I was just doing a little maintenance on my project, and I noticed that when I ran it, the problem I discuss in this post had returned. I knew that it worked last time I ran it, so I eventually narrowed the problem down to the fact that I had installed a newer version of the WPF Toolkit (Feb '10). When I reverted to the June '09 version, everything worked fine again. So, I'm now doing something I should have done in the first place: I'm including the WPFToolkit.dll that works in my solution folder and checking it into version control. It's unfortunate, though, that the newer toolkit has a breaking change.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 DisplayIndex 绑定中设置
FallbackValue=
,其中
是列的索引。例如:Set
FallbackValue=<idx>
in your DisplayIndex binding, where<idx>
is your column's index. For example:(我之前的答案偏离了轨道 - 所以我删除了它 - 我会在我的机器上重现错误后再次尝试回答)
您遇到的问题源于这样一个事实:当第一次评估绑定时, < code>DataContext 属性仍设置为
null
。由于某种奇怪的原因(但我不知道),这导致绑定在-1
处求值。但是,如果您确保在评估绑定之前设置DataContext
,那么就可以了。不幸的是,这可能只能在代码隐藏中实现 - 因此在运行时,而不是在设计时。所以在设计的时候我还是不知道如何规避这个错误。为此,请在调用
InitializeComponent
之前设置窗口的DataContext
属性,如下所示:希望这会有所帮助。
(My previous answer was way off track - so I deleted it - I'll try to answer again after reproducing the error on my machine)
The problem you encounter stems from the fact that when the bindings are evaluated for the first time, the
DataContext
property is still set tonull
. This, for some strange reason, yet unknown to me, causes the binding to evaluate at-1
. However if you make sure to set theDataContext
before the bindings are evaluated you'll be ok. Unfortunately this might only be possible in code-behind - hence during run-time, and not in design time. So in design time I still don't know how to circumvent the error.To do that, set the
DataContext
property of the window before the call toInitializeComponent
thus:Hope this helps.
我将其添加为答案,因为我还无法发表评论。 DisplayIndex 的值设置为 -1 的原因是:
来源: http://msdn.microsoft.com/en-us/library/vstudio/system.windows.controls.datagridcolumn.displayindex(v=vs.100).aspx
所以我想可以检查当使用上述事件更改该值时。
Aviad 提到的解决方案对我不起作用。我的 Datagrid 位于 UserControl 中,与 OP 相同,并更改了
ViewModel
构造函数、DataContext
声明和InitializeComponent()
的顺序代码> 方法没有帮助。另一方面,Pakman 的
FallbackValue
方法效果非常好。I'm adding this as an answer since I can't comment yet. The reason why the value of the DisplayIndex is set to -1 is :
Source: http://msdn.microsoft.com/en-us/library/vstudio/system.windows.controls.datagridcolumn.displayindex(v=vs.100).aspx
So I suppose that it is possible to check this value when it is changed using the aforementioned event.
The solution mentioned by Aviad didn't work for me. I have my Datagrid in a UserControl, same as the OP, and changing the order of the
ViewModel
constructor, theDataContext
declaration, and theInitializeComponent()
method didn't help.Pakman's
FallbackValue
method worked very well, on the other hand.