2011-10-08 11 views
19

Quando seleziono (facendo clic o tramite tastiera) una riga vuota sul mio DataGrid (quando voglio aggiungere una nuova riga), si verifica un errore di convalida inaspettato (ma senza eccezioni) - il bordo di datagrid cambia in rosso, come puoi vedere nell'immagine qui sotto. Quando clicco una seconda volta su una riga vuota, il bordo rosso scompare. Tutto il resto funziona bene, la nuova riga viene aggiunta. Inoltre, non ho regole di convalida. E quando faccio una riga con testo vuoto, il valore è valido.Bordo rosso inatteso (errore di convalida) su DataGrid quando si seleziona una riga vuota

Non voglio questo comportamento e questo bordo rosso, nessuno lo sa, perché questo succede e come risolverlo? Perché e dove fallisce qualche convalida?

enter image description here

Qui di seguito aggiungo un po 'di codice sorgente:

definizione DataGrid in XAML:

<DataGrid IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name" 
ItemsSource="{Binding Path=ConfigFiles}" SelectedItem="{Binding Path=SelectedConfigFile}" 
       Grid.Column="1" Height="87" Margin="0,26,11,32" Style="{DynamicResource DataGridStyle}"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Width="1*" Binding="{Binding Name}" /> 
     </DataGrid.Columns> 
    </DataGrid> 

parte del mio ViewModel:

public class ManageModulesVM : BaseVM // Implements INotifyPropertyChanged 
{ 
    // ... 

    public ObservableCollection<ConfigFile> ConfigFiles 
    { 
     get { return selectedModule == null ? null : selectedModule.ConfigFiles; } 
     set 
     { 
      selectedModule.ConfigFiles = value; 
      OnPropertyChanged(() => ConfigFiles); 
     } 
    } 

    public ConfigFile SelectedConfigFile 
    { 
     get { return selectedModule == null ? null : selectedModule.SelectedConfigFile; } 
     set 
     { 
      if (value != null) 
      { 
       selectedModule.SelectedConfigFile = value; 
      } 
      OnPropertyChanged(() => SelectedConfigFile); 
      OnPropertyChanged(() => Parameters); 
     } 
    } 

    // ... 
} 

ConfigFile classe:

Modifica: Dopo un'ulteriore analisi, so che SelectedItem Binding sta causando problemi (quando rimuovo questa associazione, l'errore di validazione smette di apparire), ma non so ancora perché e come risolverlo.

+0

Non so che questo è il tuo problema, ma bisogna doppi riferimenti a legame a Nome. Rimuoverei il DisplayMemberPath. È anche possibile collegare un pass through converter (da stringa a stringa) sul nome e in questo modo è possibile rilevare l'eccezione. E metterei esplicitamente mode = twoway sul binding. – Paparazzi

+1

@BalamBalam buon punto, non ha risolto il mio problema, ma è stato utile anche. –

risposta

20

Ho trovato la mia soluzione a questa domanda. Ho scritto un convertitore di valori e la legò al legame:

(SelectedItem="{Binding Path=SelectedConfigFile,Converter={StaticResource configFileConverter}}")

La classe convertitore:

namespace Converters 
{ 
    public class SelectedConfigFileConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      return value; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      if(value is ConfigFile) 
       return value; 
      return null; 
     } 
    } 
} 

Definire risorsa nel resources.xaml di file (o in qualsiasi altro luogo risorse):

<ResourceDictionary (...) xmlns:conv="clr-namespace:Converters" > 
    <conv:SelectedConfigFileConverter x:Key="configFileConverter" /> 
</ResourceDictionary> 

Il vantaggio di questa soluzione è che il tipo di proprietà SelectedConfigFile non è stato modificato (nel generale object tipo) quindi è ancora fortemente digitato.

+2

Si dovrebbe contrassegnare questo come la risposta, in quanto è una soluzione più corretta. Vedi http://blog.spencen.com/2009/04/30/problems-binding-to-selectedvalue-with-microsoftrsquos-wpf-datagrid.aspx per una soluzione simile. – BKewl

+0

ha funzionato per me .. Grazie @Lucasus –

6

Per ottenere il motivo, quando si fa clic sulla nuova riga di DataGrid in modalità Debug, vedere la finestra di debug. Ci sono i primi messaggi di eccezione che ti daranno l'idea del perché il tuo problema si è verificato.

Sì, il problema deriva dalla trasmissione dei tipi. È necessario modificare il tipo di SelectedItem per il tipo di oggetto come di seguito.

public class ManageModulesVM : BaseVM // Implements INotifyPropertyChanged 
{ 
    // ... 

    public object SelectedConfigFile 
    { 
     get { return selectedModule == null ? null : selectedModule.SelectedConfigFile; } 
     set 
     { 
      if (value != null) 
      { 
       selectedModule.SelectedConfigFile = value; 
      } 
      OnPropertyChanged(() => SelectedConfigFile); 
      OnPropertyChanged(() => Parameters); 
     } 
    } 

    // ... 
} 
+0

Grazie, ha funzionato :) E sì, c'era un'eccezione (Impossibile convertire '{NewItemPlaceholder}' dal tipo 'NamedObject' per digitare 'ConfigFile') nella finestra di output di debug di Visual Studio, sono nuovo a WPF, non l'ho fatto sappi che tali informazioni preziose sono scritte lì. –

+0

Questo post riguarda davvero _how to debug_ piuttosto che _suggesting a solution_ per l'OP. Si prega di vedere ** Łukasz Wiatrak ** segnato risposta sopra. – MickyD

+1

@MickyDuncan Sì, potresti avere ragione, ma come puoi vedere, la mia risposta mostra una soluzione di base, che consentirebbe a @ Łukasz Wiatrak di creare 'SelectedConfigFileConverter'. È gratis che tu possa pensare @ Łukasz La risposta di Wiatrak è migliore, ma non posso essere d'accordo "Questo post riguarda davvero come eseguire il debug piuttosto che suggerire una soluzione per l'OP" perché ho mostrato la soluzione sopra per risolvere questo problema. –

4

Si può solo aggiungere questa riga al vostro DataGrid:

<DataGrid Validation.ErrorTemplate="{x:Null}" /> 
+0

questa non è una buona soluzione perché rimuoverà il modello di convalida, quindi come possiamo personalizzare la convalida? – Hisham

3

Ecco un convertitore general-purpose è possibile utilizzare per qualsiasi DataGrid, vincolante qualsiasi tipo di elemento:

public class DataGridItemConverter : MarkupExtension, IValueConverter 
    { 
    static DataGridItemConverter converter; 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
     return value; 
     } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
     return (value != null && value.GetType() == targetType) ? value : null; 
     } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
     { 
     if (converter == null) 
      converter = new DataGridItemConverter(); 
     return converter; 
     } 
    } 

Dal momento che implementa MarkupExtension non hai nemmeno bisogno di definire una risorsa statica, puoi semplicemente fare riferimento in questo modo:

SelectedItem="{Binding SelectedThing,Converter={conv:DataGridItemConverter}}" 
+0

bella soluzione +1 – Hisham

1

Si può solo aggiungere questa riga al vostro DataGrid:

<DataGrid Validation.ErrorTemplate="{x:Null}" /> 

che possa risolvere il problema

Problemi correlati