2011-10-08 2 views
19

Po wybraniu (przez kliknięcie lub klawiaturą) pustego wiersza w mojej DataGrid (gdy chcę dodać nowy wiersz), pojawia się nieoczekiwany błąd sprawdzania poprawności (ale bez wyjątku) - granica zmiany datagridu na czerwony kolor, jak widać na poniższym obrazku. Kiedy kliknę drugi raz na pustym wierszu, czerwona ramka zniknie. Wszystko inne działa poprawnie, dodawany jest nowy wiersz. Poza tym nie mam żadnych reguł sprawdzania poprawności. A kiedy robię wiersz z pustym tekstem, wartość jest poprawna.Nieoczekiwane czerwone obramowanie (błąd sprawdzania poprawności) w DataGrid podczas wybierania pustego wiersza

Nie chcę tego zachowania i tej czerwonej granicy, czy ktoś wie, dlaczego tak się dzieje i jak to naprawić? Dlaczego i gdzie kończy się proces sprawdzania poprawności?

enter image description here

Poniżej dołączania kodu źródłowego:

definicję DataGrid w 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> 

My ViewModel za część:

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 klasa:

public class ConfigFile 
{ 
    public string Name { get; set; } 
    public IList<Parameter> Parameters { get; set; } 

    public ConfigFile() { Name = ""; Parameters = new List<Parameter>(); } 
} 

Edit: Po dalszych badań wiem, że SelectedItem Oprawa jest przyczyną problemów (gdy usunę tego wiązania, błąd walidacji przestanie się pojawiać), ale nadal nie wiem dlaczego i jak to naprawić.

+0

nie wiem, że jest to problem, ale masz podwójne odniesień do wiązania się z nazwy. Usunąłbym DisplayMemberPath. Możesz również dołączyć do nazwy konwerter pass thru (string to string), dzięki czemu możesz złapać wyjątek. I jawnie umieściłbym mode = twoway na powiązaniu. – Paparazzi

+1

@BalamBalam dobry punkt, To nie rozwiązało mojego problemu, ale też było pomocne. –

Odpowiedz

20

Znalazłem własne rozwiązanie tego pytania. Pisałem konwerter wartości i związał go na wiązanie:

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

Klasa konwerter:

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; 
     } 
    } 
} 

Definiowanie zasobów w resources.xaml pliku (lub w każdym innym miejscu zasobów):

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

Zaletą tego rozwiązania jest to, że typ właściwości SelectedConfigFile nie zmienił się (do ogólnego object), więc nadal jest mocno napisany.

+2

Należy oznaczyć to jako odpowiedź, ponieważ jest to poprawniejsze rozwiązanie. Zobacz http://blog.spencen.com/2009/04/30/problems-binding-to-selectedvalue-with-microsoftrsquos-wpf-datagrid.aspx dla podobnego rozwiązania. – BKewl

+0

to działało dla mnie .. Dzięki @Lucasus –

6

Aby poznać przyczynę, po kliknięciu nowego wiersza DataGrid w trybie debugowania, zobacz okno debugowania. Istnieją pierwsze komunikaty o wyjątkach, które dadzą ci pojęcie, dlaczego wystąpił problem.

Tak, problem dotyczy odlewania. Musisz zmodyfikować typ SelectedItem do typu obiektu, jak poniżej.

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

Dzięki, zadziałało :) I tak, był wyjątek (Nie można przekonwertować '{NewItemPlaceholder}' z typu 'NamedObject' na typ 'ConfigFile') w oknie wyjściowym debugowania Visual Studio, jestem nowy w WPF, nie robiłem tego wiem, że tam są zapisywane takie cenne informacje. –

+0

Ten post jest naprawdę o _how do debugowania_, a nie _sugkowaniu rozwiązania_ dla OP. Zobacz ** Łukasz Wiatrak ** zaznaczony powyżej. – MickyD

+1

@MickyDuncan Tak, możesz mieć rację, ale jak widać, moja odpowiedź pokazuje podstawowe rozwiązanie, które pozwoliłoby @ Łukaszowi Wiatrakowi stworzyć 'SelectedConfigFileConverter'. To za darmo, że można pomyśleć. Odpowiedź Łukasza Wiatrak jest lepsza, ale nie mogę się zgodzić "Ten post naprawdę mówi o debugowaniu, a nie sugerowaniu rozwiązania dla OP", ponieważ pokazałem powyższe rozwiązanie, aby rozwiązać ten problem. –

4

Można tylko dodać tę linię do DataGrid:

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

to nie jest dobre rozwiązanie, ponieważ usunie szablon walidacji, więc w jaki sposób możemy dostosować walidację? – Hisham

3

Oto konwerter ogólnego przeznaczenia można użyć dla każdej DataGrid wiążące jakiejkolwiek pozycji:

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; 
     } 
    } 

Ponieważ realizuje MarkupExtension, którego nie trzeba definiować statycznego zasobu, można po prostu odwoływać się do niego w następujący sposób:

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

fajne rozwiązanie +1 – Hisham

1

Można tylko dodać tę linię do DataGrid:

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

To rozwiąże problem