2012-02-26 22 views
9

Contesto/contesto per questa domanda: Ho un'applicazione desktop WPF. Usa LINQ to SQL per connettersi al suo database SQL e visualizza i suoi dati in Datagrids WPF. Funzionava abbastanza bene, ma le prestazioni erano un problema perché LINQ può essere mortalmente lento, quindi ho spostato il più possibile i miei controlli di logica e UI dai contesti del database LINQ il più possibile, e invece li ho caricati in variabili locali che sono molto simili a gli oggetti LINQ, che migliorano notevolmente le prestazioni.Come si risolve l'eccezione "Binding bidirezionale richiede l'eccezione Path or XPath" in Datagrids WPF?

Il problema: Come verifico i miei DataGrid, ora sto ottenendo una nuova eccezione "binding bidirezionale richiede Path o XPath." Quando si tenta di modificare il valore in un certo (intero) colonna di un Datagrid, sebbene la modifica delle colonne stringa funzionasse correttamente. Non capisco perché sto ricevendo questo, o cosa fare al riguardo.

Quindi ha funzionato quando il datagrid.datacontext è stato impostato su un'associazione di entità LINQ, ma funziona quasi solo quando è impostato su un elenco di oggetti semplici. Ho provato a cambiare la lista in ObservableCollection, ma questo non ha avuto alcun effetto apparente.

Ho esaminato una dozzina di domande correlate diverse qui e su altri siti, e non vedo nulla che sembra aiutare.

Attualmente ho:

<DataGrid Margin="12,110,12,0" x:Name="dgDays" ItemsSource="{Binding}" 
       Height="165" VerticalAlignment="Top" MinHeight="0" 
       AutoGenerateColumns="False" 
       SelectionChanged="dgDays_SelectionChanged"> 

...

<DataGrid.Columns> 
      <DataGridComboBoxColumn Width="80" Header="Cook" x:Name="_DailyCookCombo" SelectedItemBinding="{Binding sCook}"/> 
      <DataGridComboBoxColumn Width="80" Header="Eat" x:Name="_DailyDayCombo" SelectedItemBinding="{Binding sDay}"/> 
      <DataGridTextColumn Width="52" Header="Prot" Binding="{Binding Protein}" /> 
      <DataGridTextColumn Width="52" Header="Carb" Binding="{Binding Carb}" /> 
      <DataGridTextColumn Width="52" Header="Fat" Binding="{Binding Fat}" /> 
      <DataGridTextColumn Width="62" Header="Prot %" Binding="{Binding ProteinPercent}" /> 
      <DataGridTextColumn Width="62" Header="Carb %" Binding="{Binding CarbPercent}" /> 
      <DataGridTextColumn Width="62" Header="Fat %" Binding="{Binding FatPercent}" /> 
      <DataGridTextColumn Width="116" Header="non PFW meals" Binding="{Binding NonPFWMeals}" /> 
      <DataGridTextColumn Width="55" Header="Prot" Binding="{Binding CalcProt}" IsReadOnly="True" /> 
      <DataGridTextColumn Width="55" Header="Carb" Binding="{Binding CalcCarbs}" IsReadOnly="True" /> 
      <DataGridTextColumn Width="55" Header="Fat" Binding="{Binding CalcFat}" IsReadOnly="True" /> 
      <DataGridTextColumn Width="65" Header="KCal" Binding="{Binding CalcKCal}" IsReadOnly="True" /> 
      <DataGridCheckBoxColumn Width="32" Header="Skip" Binding="{Binding Skip}" /> 
      <DataGridTextColumn Width="70" Header="Date" Binding="{Binding sNextDate}" IsReadOnly="True" /> 
     </DataGrid.Columns> 
    </DataGrid> 

che è vincolato dal codice:

dgDays.DataContext = TheMember.RAM_Member_Requirements_Days; 

che è definito come:

public ObservableCollection<RAM_Member_Requirements_Day> RAM_Member_Requirements_Days = new ObservableCollection<RAM_Member_Requirements_Day>(); 

i cui membri sono vincolati:

public class RAM_Member_Requirements_Day : INotifyPropertyChanged 
{ 
    // RAM equivalents of DB values: 
public System.Nullable<decimal> Protein; 
public System.Nullable<decimal> Carb; 
public System.Nullable<decimal> Fat; 
public System.Nullable<decimal> ProteinPercent; 
public System.Nullable<decimal> CarbPercent; 
public System.Nullable<decimal> FatPercent; 
public System.Nullable<int> NonPFWMeals; 
public System.Nullable<bool> Skip; 
public System.Nullable<System.DateTime> SkipDate; 

Ho trovato un molto semplice correzione poco dopo aver digitato questo, che vi posterò quando il sito mi lascia dopo il suo ritardo di 8 ore.

risposta

3

Ok, beh, dopo aver digitato tutto ciò, ho provato qualcosa che funzionava. Sto postando comunque, nel caso in cui aiuti gli altri.

La soluzione era quella di aggiungere alle variabili membro problema che sono tenuti:

{get; impostato; }

Come in:

public System.Nullable<decimal> Protein { get; set; } 
    public System.Nullable<decimal> Carb { get; set; } 
    public System.Nullable<decimal> Fat { get; set; } 
    public System.Nullable<decimal> ProteinPercent { get; set; } 
    public System.Nullable<decimal> CarbPercent { get; set; } 
    public System.Nullable<decimal> FatPercent { get; set; } 
    public System.Nullable<int> NonPFWMeals { get; set; } 
    public System.Nullable<bool> Skip { get; set; } 
+2

Nel caso in cui questo sia misterioso per te, è perché non puoi associare a campi, solo proprietà. Per una spiegazione del perché, vedi: http://stackoverflow.com/questions/842575/why-does-wpf-support-binding-to-properties-of-an-object-but-not-fields – MatrixManAtYrService

+0

@MatrixManAtYrService Grazie, anche se dopo averlo letto, è ancora misterioso per me. Apparentemente avrei bisogno di leggere le definizioni e le differenze tra campi e proprietà. – Dronz

+1

Heh. Ok, facendo un po 'di lettura, vedo che ho usato campi e proprietà senza sapere cosa C# li ha chiamati. Interessante, grazie. – Dronz

3

A "binding bidirezionale richiede Path o XPath" guasto può essere causa di una piccola differenza nel nome del percorso nel XAML vs quello nel C# Binding elemento. La lettera maiuscola è davvero importante! Questo era il mio problema

XAML:

<DataGridTextColumn Binding="{Binding Path=TotalHeure}" ClipboardContentBinding="{x:Null}" Header="Total Heures" Width="80"/> 

C#:

public string Totalheure { get; set; } 

questo causerà un bidirezionale vincolante che imponga un percorso o un errore di XPath perché non sono esattamente lo stesso e i programmi non è in grado di trova il percorso vincolante!

Forse sarà aiutare qualcun altro che ha fatto lo stesso errore

5

mi sono imbattuto in questo problema con una casella di testo associato. La mia soluzione era di legarsi esplicitamente a ".":

<TextBox Text="{Binding Path=.}" /> 

Questo ha fatto il trucco.