Моя привязка данных с конвертером значений не работает - PullRequest
1 голос
/ 26 июня 2009

У меня есть простой предметный класс, который выглядит так:

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

И ValueConverter, который выглядит так:

[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();
    }
}

В моем окне WPF я объявляю DependencyProperty (называемый Items), который содержит список объектов Item (List ) и создает ComboBox, который связывается с этим DependencyProperty, используя этот XAML-код:

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

Если я выполню приведенный ниже код один раз, привязка данных будет работать нормально, однако преобразование значения завершится неудачно, если я выполню его снова:

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

Проблема в том, что методу ItemToStringConverter.Convert теперь передается строковый объект в качестве первого параметра вместо объекта Item?

Что я делаю не так?

С уважением, Кеннет

Ответы [ 3 ]

0 голосов
/ 26 июня 2009

Альтернативный подход,

  1. Вы можете получить свой класс из Object вместо DependencyObject
  2. Вы можете реализовать интерфейс INotifyPropertyChange
  3. И вы можете реализовать свойство только для чтения и событие уведомления о пожаре при изменении любого из параметров «Нет» или «Имя».

открытый класс 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;
    }
}

}

Теперь вы можете связывать только свойство «DisplayName» вместо конвертера.

  1. Преобразователи довольно сложны для реализации
  2. И классы на основе DependencyObject следует использовать только для целей пользовательского интерфейса
0 голосов
/ 26 июня 2009

Простой обходной путь - проверить тип, передаваемый вашему ValueConverter. Измените метод преобразования следующим образом:

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 голосов
/ 26 июня 2009

Если вы хотите использовать привязку данных, вы должны назначить свою коллекцию ItemsSource, а не Items. Я думаю, что это, вероятно, решит эту проблему.

...