2010-01-24 58 views
12

問題使用綁定在數據網格

我有一個WPF工具包DataGrid,我想能夠幾個預置柱訂單之間進行切換來控制列的順序。這是一個MVVM項目,所以列訂單存儲在ViewModel中。問題是,我無法獲得綁定爲DisplayIndex屬性工作。不管我怎麼努力,包括甜方法this Josh Smith tutorial,我得到:

的的DisplayIndex與頭「ID」的DataGridColumn超出範圍。 DisplayIndex必須大於或等於0且小於Columns.Count。參數名稱:displayIndex。實際值爲-1。

有沒有什麼解決方法呢?

我在下面列出了我的測試代碼。如果您發現任何問題,請告訴我。


視圖模型代碼

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'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> 

注:如果我只是使用普通的號碼DisplayIndex,一切工作正常,那麼問題肯定是綁定。


更新2010年5月1日

我只是在做我的項目很少的維護,我注意到,當我跑了,我在這個帖子討論這個問題回來了。我知道它在我上次運行它的時候起作用,所以我最終將問題縮小到了我已經安裝了WPF Toolkit的新版本(10年2月)。當我回到2009年6月份的版本時,一切正常。所以,我現在正在做一些我應該首先完成的工作:我將WPFToolkit.dll包含在我的解決方案文件夾中,並將其檢入版本控制。但不幸的是,新的工具包有一個突破性的變化。

回答

4

(我以前的答案是方式偏離了軌道 - 所以我刪除了 - 我會盡量在我的機器上重現錯誤後,再次回答)

您遇到的問題來源於這樣的事實,當綁定第一次評估時,DataContext屬性仍設置爲null。這個,出於某種奇怪的原因,我還不知道,導致綁定評估在-1。但是,如果您確定在之前設置DataContext,則評估綁定即可。不幸的是,這可能只有在代碼隱藏時纔有可能 - 因此在運行時期間,而不是在設計時間內。所以在設計時我仍然不知道如何規避錯誤。

要做到這一點,因此設置窗口的DataContext屬性調用之前InitializeComponent

public MainWindow() 
{ 
    DataContext = new MainViewModel(); 
    InitializeComponent(); 
} 

希望這有助於。

+0

嗯,這很有趣。如果我運行我的測試應用程序,您的修復程序完美運行在我的真實應用程序中,所討論的DataGrid實際上是在一個UserControl中,並且由於某種原因,如果我應用了'DataContextSpy'(我之前沒有嘗試過,因爲它沒有通過測試應用程序) ,即使我不推遲調用InitializeComponent(),它也可以工作。我認爲這一定是因爲我只是在ContentControl上設置Content,而不是做'window.Show()'。無論如何,感謝您花時間爲我解決這個問題(+1和√)。 – devuxer 2010-01-24 21:41:23

12

在您的DisplayIndex綁定中設置FallbackValue=<idx>,其中<idx>是您的列索引。例如:

DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.IdDisplayIndex, FallbackValue=0}" /> 
+2

完美 - 而且優雅。 – ShadowChaser 2012-02-10 16:42:52

+1

這是走下坡路的方式。 – 2013-01-30 17:18:43

1

由於我還不能評論,我添加了這個答案作爲答案。爲什麼的DisplayIndex的值設置爲-1的原因是:

的的DisplayIndex財產有它被添加 到DataGrid.Columns收集之前的-1的默認值。將 列添加到DataGrid時更新此值。

DataGrid要求每列 的DisplayIndex屬性必須是從0到列Count-1的唯一整數。因此,當一列的DisplayIndex更改時, 的更改通常會導致其他列的DisplayIndex也發生更改。

對DisplayIndex值的限制由 ValidateValueCallback機制強制執行。如果您嘗試設置值爲 無效,則會引發運行時異常。

當DisplayIndex屬性的值發生更改時,會引發 DataGrid.ColumnDisplayIndexChanged事件。

來源:http://msdn.microsoft.com/en-us/library/vstudio/system.windows.controls.datagridcolumn.displayindex(v=vs.100).aspx

所以我想這是可以檢查這個值時,它使用的是上述事件的發生變化。

Aviad提到的解決方案並不適合我。我有一個UserControl中的Datagrid,與OP相同,並且更改構造函數ViewModelDataContext聲明和InitializeComponent()方法的順序沒有任何幫助。

帕克曼的FallbackValue方法工作得很好,另一方面。