Meu banco de dados com conversor de valor não funciona
-
20-08-2019 - |
Pergunta
Eu tenho uma classe de itens simples, que se parece com o seguinte:
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));
}
E um valueConverter, que se parece com o seguinte:
[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();
}
}
Na minha janela WPF, declaro uma dependênciaProperty (chamado itens) que contém uma lista de objetos de itens (List <tem>) e cria um ComboBox que se liga a essa dependênciaProperty usando este xaml-código:
<ComboBox ItemsSource="{Binding ElementName=mainWindow, Path=Items}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource itemToStringConverter}}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Se eu executar o código abaixo uma vez, o banco de dados funciona bem, como a conversão de valor falha se eu o executar novamente:
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};
O problema é que o método ItemToStringConverter.Convert agora é passado um objeto de string como o primeiro parâmetro em vez de um objeto de item?
O que estou fazendo errado?
Atenciosamente, Kenneth
Solução
Solução alternativa simples seria verificar o tipo passado para o seu valueConverter. Alterar o método convertido da seguinte maneira:
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();
}
Outras dicas
Abordagem alternativa,
- Você pode derivar sua classe do objeto em vez de dependencyObject
- Você pode implementar a interface inotifyPropertyChange
- E você pode implementar uma propriedade de leitura e um evento Notify quando alguma das alterações não ou de nomes.
Item da classe pública: 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;
}
}
}
Agora você só pode vincular a propriedade "DisplayName" em vez de conversor ..
- Os conversores são bastante complexos para implementar
- E as classes baseadas em objeto dependencybject devem ser usadas apenas para fins de interface do usuário
Se você deseja usar o banco de dados, atribua sua coleção ao itemsSource, não aos itens. Eu acho que isso provavelmente resolveria esse problema.