2010-02-23 12 views
10

W mojej aplikacji WPF mam Canvas, w którym robię trochę rysunku. Wcześniej zajmowałem się rysunkiem w kodzie, ale teraz wszystko zapisałem na ViewModelu. To daje mi pewne wyzwania ..Wiązanie płótna WPF Canvas Children to an ObservableCollection

Mam kilka obiektów InkPresenter zawierających obrysy. Earier dodałem je jako dzieci na płótnie w kodzie tyłu - tak:

// Build an InkPresenter: 
var someInkPresenter = BuildInkPresenter(..); 
//_myCanvas is the <Canvas> I want to display it in: 
_myCanvas.Children.Add(someInkPresenter); 

Teraz - nie budować InkPresenter w kodzie opóźnieniem w XAML, który przechowuje _myCanvas muszę to zrobić inaczej. Co chciałbym zrobić, to stworzyć InkPresenter i dodać go do kolekcji:

public ObservableCollection<InkPresenter> Drawings; 

Mój problem jest teraz jak związać płótna do tego ObservableCollection - i mają InkPresenters wyświetlany po dodaniu do kolekcji. Czy mogę to w jakiś sposób osiągnąć za pomocą Wiązania Danych?

Odpowiedz

16

Myślę, że możesz to zrobić pod numerem ItemsControl + ItemsPanelTemplate. Tak:

<ItemsControl ItemsSource="{Binding YourCollection}"> 
    <ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <Canvas /> 
    </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    </ItemsControl> 

Aby dowiedzieć się więcej na temat tej metody można znaleźć w Dr.WPF: ItemsControl: A to Z (P is for Panel)

+0

Thx! Brzmi rozsądnie. Rzuć okiem na to! – stiank81

+1

To jest zwykle podejście, które podejmiesz, ale w tym przypadku prawdopodobnie będziesz mieć problemy, ponieważ InkPresenters nie będą bezpośrednimi dziećmi Canvas, tak jak to jest kiedy dodajesz je w kodzie. Zamiast tego Visual Tree będzie miało dodatkowy ContentPresenter wstrzykiwany wokół każdego elementu InkPresenter. Aby ta metoda działała, powinieneś przyjrzeć się wyciągnięciu rzeczywistych danych (obrysów) z każdego InkPresenter i przechowywaniu kolekcji tych w twojej maszynie wirtualnej. Następnie można utworzyć niestandardowy ItemsControl, który zastępuje GetContainerForItemOverride, aby zwrócić InkPresenter. –

+0

Nie mogę się z tobą zgodzić John ... To ItemControl. Wykorzystuje UIElement jako domyślny kontener ... – Anvaka

10

Rozwiązanie Anvaka sugerowane jest super, ale jak John Bowen podkreślić trzeba wiedzieć nieco więcej , jeśli chcesz faktycznie powiązać swoje produkty z właściwościami dołączonymi do Canvas.

Oto przykład, w jaki sposób wiążą się Canvas.Left i Canvas.Top:

<ItemsControl ItemsSource="{Binding YourCollection}"> 
<ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <Canvas /> 
    </ItemsPanelTemplate> 
</ItemsControl.ItemsPanel> 
<ItemsControl.ItemContainerStyle> 
    <Style TargetType="ContentPresenter"> 
     <Setter Property="Canvas.Left" Value="{Binding YourModelLeft}" /> 
     <Setter Property="Canvas.Top" Value="{Binding YourModelTop}" /> 
    </Style> 
</ItemsControl.ItemContainerStyle> 

BTW, znalazłem rozwiązanie na this question po Próbowałem sugestię Anvaka, w którym wiązania nie działa .

Mam nadzieję, że to pomoże innym, szukając tej samej odpowiedzi.

+0

Dzięki, dokładnie to, czego szukałem. – Cousken