2009-06-26 5 views
1

J'ai une simple classe d'objet, qui ressemble à ceci:Mon databinding avec convertisseur de valeur ne fonctionne pas

public class Item : DependencyObject 
{ 
    public int No 
    { 
     get { return (int)GetValue(NoProperty); } 
     set { SetValue(NoProperty, value); } 
    } 

    public string Name 
    { 
     get { return (string)GetValue(NameProperty); } 
     set { SetValue(NameProperty, value); } 
    } 

    public static readonly DependencyProperty NoProperty = DependencyProperty.Register("No", typeof(int), typeof(Item)); 
    public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(Item)); 
} 

Et ValueConverter, qui ressemble à ceci:

[ValueConversion(typeof(Item), typeof(string))] 
internal class ItemToStringConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) 
     { 
      return null; 
     } 

     var item = ((Item)value); 

     var sb = new StringBuilder(); 
     sb.AppendFormat("Item # {0}", item.No); 

     if (string.IsNullOrEmpty(item.Name) == false) 
     { 
      sb.AppendFormat(" - [{0}]", item.Name); 
     } 

     return sb.ToString(); 
    } 


    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

sur ma fenêtre WPF, je déclare un DependencyProperty (appelé Items) qui contient une liste d'objets Item (Liste < Item>) et crée un ComboBox qui lie à cette DependencyProperty en utilisant ce code XAML:

<ComboBox ItemsSource="{Binding ElementName=mainWindow, Path=Items}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Converter={StaticResource itemToStringConverter}}"/> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

Si j'exécute le code ci-dessous une fois, la liaison de données fonctionne très bien, howevery la convertion de valeur échoue si je l'exécute à nouveau:

var item1 = new Item {Name = "Item A", No = 1}; 
var item2 = new Item {Name = "Item B", No = 2}; 
var item3 = new Item {Name = "Item C", No = 3}; 
Items = new List<Item> {item1, item2, item3}; 

Le problème est que la méthode ItemToStringConverter.Convert est maintenant adopté une chaîne -object comme premier paramètre au lieu d'un objet-objet?

Qu'est-ce que je fais mal?

Cordialement, Kenneth

Répondre

0

Une solution de contournement simple consiste à vérifier le type transmis à votre ValueConverter. Changer la méthode de conversion comme suit:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { 
     var item = value as Item; 
     if(item == null) { return null; } 
     var sb = new StringBuilder(); 
     sb.AppendFormat("Item # {0}", item.No); 
     if(string.IsNullOrEmpty(item.Name) == false) { 
      sb.AppendFormat(" - [{0}]", item.Name); 
     } 
     return sb.ToString(); 
    } 
+0

C'est exactement ce que j'ai fait jusqu'ici, mais je voulais vraiment savoir pourquoi la méthode Convert a été appelée avec une valeur de chaîne :) – kennethkryger

-1

Si vous souhaitez utiliser la liaison de données, vous devez affecter votre collection à ItemsSource, pas les objets. Je pense que cela réglerait probablement ce problème.

+0

Je pense que je l'ai fait, n'est-ce pas? La propriété ItemsSource de ComboBox est liée à la propriété Items ... Veuillez me corriger si je me trompe. – kennethkryger

+0

D'oh! J'ai manqué ça - j'ai supposé que c'était les objets de ListBox auxquels vous étiez assignés, pas ceux de vos objets. Ma faute. –

0

approche alternative,

  1. Vous pouvez dériver votre classe d'objets au lieu de DependencyObject
  2. Vous pouvez implémenter l'interface INotifyPropertyChange
  3. Et vous pouvez mettre en œuvre une propriété en lecture seule et le feu notifier événement lorsque l'un des Non ou Changements de nom.

public class Article: System.ComponentModel.INotifyPropertyChanged {

public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; 


private void Notify(string p) 
{ 
    if (PropertyChanged != null) 
     PropertyChanged(this, 
      new System.ComponentModel.PropertyChangedEventArgs(p)); 
} 

private int _No = 0; 
public int No 
{ 
    get 
    { 
     return _No; 
    } 
    set 
    { 
     _No = value; 
     Notify("No"); 
     Notify("DisplayName"); 
    } 
} 


private string _Name = ""; 
public string Name 
{ 
    get 
    { 
     return _Name; 
    } 
    set 
    { 
     _Name = value; 
     Notify("Name"); 
     Notify("DisplayName"); 
    } 
} 

public string DisplayName 
{ 
    get 
    { 
     string sb = string.Format("Item # {0}", _No); 
     if (!string.IsNullOrEmpty(_Name)) 
      sb += _Name; 
     return sb; 
    } 
} 

}

Maintenant, vous ne pouvez lier la propriété "DisplayName" au lieu de convertisseur ..

  1. Convertisseurs sont assez complexes à mettre en œuvre
  2. Et Depe Les classes basées sur ndencyObject ne doivent être utilisées qu'à des fins d'interface utilisateur
+0

Mon exemple est très simplifié par rapport à mon code d'origine, et la classe Item provient de BusinessBase (j'utilise CSLA.NET). Toutefois, l'ajout d'une propriété DisplayName est une excellente idée. Mais je n'arrive toujours pas à comprendre pourquoi mon convertisseur est appelé avec une valeur de chaîne? – kennethkryger

Questions connexes