2016-10-20 6 views
0

私は3つのコレクションをまとめてバインドしたいMVVMアプリケーションです。ビューでは、TimeBoxesを持つItemsControl(依存関係プロパティTimeを持つTextBoxのみ)があります。モデルでWPF 3つのコレクションを一緒にバインドする

public class Mainwindow 
{ 
    //... 
    var Timeboxes = new ObservableCollection<TimeBox>(); 
} 

の背後にあるコードで

<Window x:Class="Scoreboard.View.MainWindow" 
    ... 
    <ItemsControl ItemsSource="{Binding TimeBoxes}"/> 
    ... 
</Window> 

私はタイムコレクションを持っていると思います。

public class GameModel 
{ 
    var Times = new ObservableCollection<Time>(); 
    // Don't know if this is how it should be 
} 

そして私は、ビューのメインウィンドウに似ているouputを持つ別のウィンドウを持っていますが、ItemsControlには国境はなく、タイムボックスを保持しています。それは何をすべき

<Window x:Class="Scoreboard.Display.DisplayWindow" 
    ... 
    <ItemsControl ItemsSource="{Binding Borders}"/> 
    ... 
</Window> 

は次のとおりです。Viewのボタン(MainWindow)上でクリックするとTimeBoxTimeBoxesコレクションに作成されます。そのTimeBoxTimeは、の新しいTimeに、GameModelに結びついています。また、Timeは、出力(表示)WindowBordersに新しいBorder(これはTimeToStringConverterがあります)のコンテンツ(ラベル)にバインドされています。 GameModelTimeが0になると、そのインスタンスはすべてのコレクションから削除されます。私の問題は、コレクション内のアイテムを別のコレクションのアイテムにバインドする方法がわかりません。 ViewModelは単純化のために省略されています。

は私が動的にTimeBoxTimeにしていることをバインドしたい要約すると1でTimeBorderへのコンテンツ:1:1の比率。

答えて

2

CollectionHelperには、2 ObservableCollectionをバインドするためのテスト済みソリューションがあります。あるコレクションからアイテムが追加または削除されると、もう一方のアイテムが更新されます。 BindメソッドはIDisposableを返します。したがって、処分すると、自動更新は終了します。 同じジェネリックタイプの2つのコレクションで動作します。あなたは、異なるタイプのコレクションを処理するための方法が必要な場合は、あなたがコメントした方法のようなシグネチャを持つメソッドを実装する必要があります:あなたはc1は、C2、C3のバインドする必要がある場合は、

[TestClass] 
public class BindTwoObservableCollections_test 
{ 
    [TestMethod] 
    public void BindTwoObservableCollections() 
    { 
     var c1 = new ObservableCollection<int>(); 
     var c2 = new ObservableCollection<int>(); 

     c1.Add(1); 
     Assert.AreEqual(0, c2.Count); 

     var subscription = CollectionHelper.Bind(c1, c2); 

     c1.Add(2); 
     Assert.AreEqual(1, c2.Count); 
     Assert.AreEqual(2, c2[0]); 

     c2.Add(3); 
     Assert.AreEqual(3, c1.Count); 
     Assert.AreEqual(3, c1[2]); 

     c2.Remove(2); 
     Assert.AreEqual(2, c1.Count); 

     subscription.Dispose(); 

     c2.Remove(3); 
     Assert.AreEqual(2, c1.Count); 
    } 
} 

public static class CollectionHelper 
{ 
    public static IDisposable Bind<T>(
     ObservableCollection<T> c1, 
     ObservableCollection<T> c2) 
    { 
     var fromC1Subscription = InternalBind(c1, c2); 
     var fromC2Subscription = InternalBind(c2, c1); 

     return new Disposable(() => 
     { 
      fromC1Subscription?.Dispose(); 
      fromC2Subscription?.Dispose(); 
     }); 
    } 

    private static IDisposable InternalBind<T>(
     ObservableCollection<T> from, 
     ObservableCollection<T> to) 
    { 
     NotifyCollectionChangedEventHandler onFromChanged = 
      (s, e) => 
      { 
       switch (e.Action) 
       { 
        case NotifyCollectionChangedAction.Add: 
         foreach (T added in e.NewItems) 
          if (!to.Contains(added)) 
           to.Add(added); 
         break; 

        case NotifyCollectionChangedAction.Remove: 
         foreach (T removed in e.OldItems) 
          to.Remove(removed); 
         break; 

        //other cases... 

        default: 
         break; 
       } 
      }; 

     from.CollectionChanged += onFromChanged; 

     return new Disposable(() => { from.CollectionChanged -= onFromChanged; }); 
    } 

    //public static IDisposable Bind<T1, T2>(
    // ObservableCollection<T1> c1, 
    // ObservableCollection<T2> c2, 
    // Func<T1, T2> converter1, 
    // Func<T2, T1> converter2) 
    //{ 
    // todo... 
    //} 
} 

public class Disposable : IDisposable 
{ 
    public Disposable(Action onDispose) 
    { 
     _onDispose = onDispose; 
    } 

    public void Dispose() 
    { 
     _onDispose?.Invoke(); 
    } 

    private Action _onDispose; 
} 

もちろん、あなたが書く:

CollectionHelper.Bind(c1, c2); 
CollectionHelper.Bind(c2, c3); 

これで十分です。

+0

ありがとう、これは甘い解決策です。私は拘束力に重点を置いていたので、私は忘れていたことを知らせました:D – Korhak

+0

"知っています、兄";) –

関連する問題