2010-02-23 45 views
10

Trong ứng dụng WPF của tôi, tôi có một Canvas trong đó tôi làm một số bản vẽ. Trước đó tôi đã xử lý bản vẽ trong đoạn mã phía sau, nhưng bây giờ tôi đã tính toán mọi thứ cho một ViewModel. Điều này mang lại cho tôi một số thách thức ..Binding WPF Canvas Trẻ em đến một ObservableCollection

Tôi có một vài đối tượng InkPresenter đang giữ Strokes. Earier tôi đã thêm chúng như trẻ em đến Canvas trong mã đằng sau - như thế này:

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

Bây giờ - chứ không phải xây dựng InkPresenter trong code-behind của XAML chứa _myCanvas tôi cần phải làm điều này khác nhau. Những gì tôi muốn làm là để tạo ra một InkPresenter và thêm nó vào một bộ sưu tập:

public ObservableCollection<InkPresenter> Drawings; 

vấn đề của tôi bây giờ là làm thế nào để ràng buộc Canvas để ObservableCollection này - và có InkPresenters hiển thị khi được bổ sung vào bộ sưu tập. Tôi có thể đạt được điều này bằng cách sử dụng Bindings dữ liệu bằng cách nào đó?

Trả lời

16

Tôi nghĩ bạn có thể làm điều này với ItemsControl + ItemsPanelTemplate. Như thế này:

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

Để tìm hiểu thêm về phương pháp này đề cập đến Dr.WPF: ItemsControl: A to Z (P is for Panel)

+0

Thx! Nghe có vẻ hợp lý. Sẽ có một cái nhìn vào nó! – stiank81

+1

Đây thường là cách tiếp cận bạn muốn thực hiện nhưng trong trường hợp này bạn có thể sẽ gặp phải vấn đề bởi vì các InkPresenters sẽ không là con trực tiếp của Canvas giống như khi bạn thêm chúng vào mã. Thay vào đó, Visual Tree sẽ có thêm một ContentPresenter bổ sung xung quanh mỗi mục InkPresenter. Để có được phương pháp này để làm việc, bạn nên xem xét kéo ra dữ liệu thực tế (Strokes) từ mỗi InkPresenter và lưu trữ một bộ sưu tập của những người trong máy ảo của bạn. Sau đó bạn có thể tạo một ItemsControl tùy chỉnh ghi đè GetContainerForItemOverride để trả về một InkPresenter. –

+0

Không thể đồng ý với bạn John ... Đó là một ItemsControl. Nó sử dụng UIElement làm container mặc định ... – Anvaka

10

Giải pháp Anvaka đề nghị là rất tốt, nhưng như John Bowen chỉ ra bạn cần phải biết thêm một chút , nếu bạn muốn thực sự ràng buộc các mục của bạn với thuộc tính được đính kèm Canvas.

Dưới đây là một ví dụ về cách để ràng buộc vào Canvas.Left và 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, tôi thấy giải pháp trên this question, sau khi tôi cố gắng gợi ý Anvaka, nơi các ràng buộc đã không làm việc .

Hy vọng điều này sẽ giúp người khác, tìm kiếm cùng một câu trả lời.

+0

Cảm ơn, chính xác những gì tôi đang tìm kiếm. – Cousken