2009-04-24 81 views
4

我做了一个CollectionToStringConverter,它可以将任何IList转换成以逗号分隔的字符串(例如“Item1,Item2,Item3”)。为什么Collection在Collection更改时未被调用?

我用这样的:

<TextBlock Text="{Binding Items, 
        Converter={StaticResource CollectionToStringConverter}}" /> 

上述作品,但只有一次,当我加载UI。 ItemsObservableCollection。文本块不更新,并且当我从Items添加或删除时,转换器不会被调用。

任何想法是什么失踪,使这项工作?

回答

6

绑定是指产生集合的属性。它将在收集实例本身发生更改时生效,而不会在收集中的项目发生更改时生效。

有相当多的方式来实现你想要的行为,其中包括:

1)绑定ItemsControl的收集和配置ItemTemplate输出一个逗号前面的文字,如果不是在最后一个项目集合。喜欢的东西:

<ItemsControl ItemsSource="{Binding Items}"> 
    <ItemsControl.ItemTemplate> 
     <TextBlock> 
      <TextBlock Visibility="{Binding RelativeSource={RelativeSource PreviousData}, Converter={StaticResource PreviousDataConverter}}" Text=", "/> 
      <TextBlock Text="{Binding .}"/> 
     </TextBlock> 
    </ItemsControl.ItemTemplate>  
</ItemsControl> 

2)编写代码,在代码隐藏要监视更改的收集和更新串接的项目到一个单一的string一个单独的属性。喜欢的东西:

public ctor() 
{ 
    _items = new ObservableCollection<string>(); 

    _items.CollectionChanged += delegate 
    { 
     UpdateDisplayString(); 
    }; 
} 

private void UpdateDisplayString() 
{ 
    var sb = new StringBuilder(); 

    //do concatentation 

    DisplayString = sb.ToString(); 
} 

3)自己写的ObservableCollection<T>子类,维持类似#2一个单独的连接字符串。

+0

我已经使用ItemsTemplate做法其实已经开始了,但代码审查过程中,我们认为这将是简单通过一个多结合转换器来完成,当观察到的集合发生变化时,认为绑定会被更新。我会恢复到该方法:)谢谢! – 2009-04-24 19:37:18

1

只有在属性更改时才会调用转换器。在这种情况下,'Items'值不会改变。当您向集合中添加或删除新项目时,绑定部分不知道这一点。

您可以扩展ObservableCollection并在其中添加一个新的String属性。请记住在您的CollectionChanged事件处理程序中更新该属性。

这里是实施

public class SpecialCollection : ObservableCollection<string>, INotifyPropertyChanged 
{ 

    public string CollectionString 
    { 
     get { return _CollectionString; } 
     set { 
      _CollectionString = value; 
      FirePropertyChangedNotification("CollectionString"); 
     } 
    } 


    protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     string str = ""; 

     foreach (string s in this) 
     { 
      str += s+","; 
     } 

     CollectionString = str; 

     base.OnCollectionChanged(e); 
    } 

    private void FirePropertyChangedNotification(string propName) 
    { 
     if (PropertyChangedEvent != null) 
      PropertyChangedEvent(this, 
       new PropertyChangedEventArgs(propName)); 
    } 

    private string _CollectionString; 
    public event PropertyChangedEventHandler PropertyChangedEvent; 

} 

而且你的XAML会像

<TextBlock DataContext={Binding specialItems} Text="{Binding CollectionString}" />