Question

J'ai une simple classe Item, qui ressemble à ceci:

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 un 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 objet DependencyProperty (appelé Items) contenant une liste d'objets Item (List < Item >) et crée un contrôle ComboBox qui se lie à cet objet DependencyProperty à l'aide de cet objet XAML- code:

<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 correctement, mais la conversion 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 passée à un objet string en tant que premier paramètre au lieu d'un objet Item?

Qu'est-ce que je fais de travers?

Cordialement, Kenneth

Était-ce utile?

La solution

Une solution simple consisterait à vérifier le type transmis à votre ValueConverter. Modifiez 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();
    }

Autres conseils

Approche alternative,

  1. Vous pouvez dériver votre classe depuis Object au lieu de DependencyObject
  2. Vous pouvez implémenter l'interface INotifyPropertyChange
  3. Et vous pouvez implémenter une propriété en lecture seule et un événement de notification d'incendie en cas de modification de No ou de nom.

Classe publique Item: 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;
    }
}

}

Vous ne pouvez désormais lier que " Nom d'affichage " propriété au lieu de convertisseur ..

  1. Les convertisseurs sont assez complexes à implémenter
  2. Et les classes basées sur DependencyObject ne doivent être utilisées qu'à des fins d'interface utilisateur

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top