2016-04-16 8 views
2

WPFでカスタムコントロールを作成しています。私はList<IMyInterface>dependency propertyにバインドします。これは次に、すべての項目を期待どおりに表示するListBoxに再度バインドされます。ObservableCollectionの場合、リストをテキストボックスにバインドできません。

このリストの1つのアイテムをTextblockにバインドしたいので、リスト全体をtextblockにバインドします。私はこの中にconverterを持っていて、私が望む単一のアイテムを抽出します。

は、それがうまく働いていますが、いくつかの理由のために、私は、実行時に私のObservabaleCollectionで値を変更すると、奇妙なことに代わりList

ObservableCollectionを使用したい、値がListBox(成功)に示されています私のtextblockではそうではありません。 converterはヒットしません!

public MainWindow() 
    { 
     InitializeComponent(); 
     this.DataContext = this; 
     this.Errors = new ObservableCollection<IEventDetail>(); 
     this.Errors.CollectionChanged += Errors_CollectionChanged; 
     var bw = new BackgroundWorker(); 
     bw.DoWork += ((o, e) => 
     { 
      System.Threading.Thread.Sleep(1500); 
      Dispatcher.Invoke(() => 
      { 
       this.Errors.Add(new MyEvents("example of some detail", "Failed title")); 
      }); 

      System.Threading.Thread.Sleep(2500); 

      Dispatcher.Invoke(() => 
      { 
       this.Errors.Add(new MyEvents("Another example", "Failed title 2")); 
      }); 
     }); 
     bw.RunWorkerAsync();//background worker for testing/debugging only 
    } 

    private void Errors_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     OnPropertyChanged("Errors"); 
    } 

    private ObservableCollection<IEventDetail> _errors; 
    public ObservableCollection<IEventDetail> Errors 
    { 
     get 
     { 
      return this._errors; 
     } 
     set 
     { 
      this._errors = value; 
      OnPropertyChanged("Errors"); 
     } 
    } 


    public event PropertyChangedEventHandler PropertyChanged; 
    public void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged == null) 
      return; 

     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

とXAMLは、単にあなたが見ることができるように、私はその後、火INotifyPropertyChangedを強制的にCollectionChangedイベントを使用しようとした

<local:Notify Events="{Binding Errors}" DockPanel.Dock="Right"/> 

ですが、それはConverterはまだListBoxが私の中に発射です罰金を更新

これはUserControls XAML

です(私は結合知って結構です)

私は別のことをする必要がありますか?コメントで述べたように

+0

問題を必要とせず、代わりにTextBlock.TextEvents.ConvertedTextにプロパティをバインドを何だろうカスタムプロパティでObservableCollection<T>から継承された独自のコレクションクラスを作成します。 xamlになければならず、onpropertychangedはobservableCollectionに暗黙的に指定されています。 (あなたはxamlを投稿していますか?)explicti双方向バインディングを設定しようとしています。UpdataSourceTrigger = PropertyChanged – Xilmiki

+0

@ Xilmiki、ありがとうございますが、バインディング**は** ListBox'で動作しますが、 'Textblock'では動作しません。だから私は2ウェイバインディングが必要かどうか分からない、または 'UpdateSourceTrigger'を使うこともありません。 – Dave

+0

明示的な双方向バインディングを設定しようとしていて、UpdataSourceTrigger = PropertyChanged = TextBoxバインディングでWPFプロジェクトで同じ問題がありました。 – Xilmiki

答えて

1

TextBlockそれはは、コレクションの新しいインスタンスが作成されない限り、それはトリガされませんEventsプロパティの変更(ないその項目)にのみ結合しました。 INotifyCollectionChangedに反応するのは、ItemsSourceの特性です。

ソリューション1

それが現時点であるとしてだけTextBlock

<TextBlock Text="{Binding ...}" x:Name="myTextBlock"/> 

をいくつかの名前を付けて手動で

を更新するために結合標的を強制あなたの UserControl内部 CollectionChangedイベントをサブスクライブするすべてのものを残します
public partial class MyUserControl : UserControl 
{ 
    public static readonly DependencyProperty EventsProperty = 
           DependencyProperty.Register("Events", 
            typeof(IEnumerable), 
            typeof(MyUserControl), 
            new PropertyMetadata(EventsPropertyChanged)); 

    private static void EventsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ((MyUserControl)d).EventsPropertyChanged(e); 
    } 

    private void EventsPropertyChanged(DependencyPropertyChangedEventArgs args) 
    { 
     var newCollection = args.NewValue as INotifyCollectionChanged; 
     if (newCollection != null) 
      newCollection.CollectionChanged += (s, e) => myTextBlock.GetBindingExpression(TextBlock.TextProperty).UpdateTarget(); 
    } 

    public IEnumerable Events 
    { 
     get { return (IEnumerable)GetValue(EventsProperty); } 
     set { SetValue(EventsProperty, value); } 
    } 

} 

ソリューション2

は、あなたのコンバータが

public class MyObservableCollection<T> : ObservableCollection<T> 
{ 
    private string _convertedText; 

    protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     base.OnCollectionChanged(e); 
     this.ConvertedText = ...; // <- do here what your IValueConverter does 
    } 

    public string ConvertedText 
    { 
     get { return _convertedText; } 
     private set 
     { 
      _convertedText = value; 
      OnPropertyChanged(new PropertyChangedEventArgs("ConvertedText")); 
     } 
    } 
} 

とコンバータ

関連する問題