2010-03-10 10 views
15

Tôi đang sử dụng ItemsControl nơi ItemsPanel được đặt thành Canvas (xem this câu hỏi để biết thêm thông tin cơ bản). Các ItemsControl được thực hiện như tôi muốn, và nó hoạt động như một nét duyên dáng khi thêm một phần tử con bằng tay bằng cách đặt nó vào ItemsControl.Items:Khi sử dụng ItemsControl ItemsControl.ItemsPanel được đặt thành Canvas, ContenPresenter đi vào và ngắt thuộc tính Canvas của tôi trên [WPF]

<ItemsControl> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Canvas IsItemsHost="True" /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.Items> 
     <Button Canvas.Left="500" Content="Button Text" /> 
    </ItemsControl.Items> 
</ItemsControl> 

Note thuộc tính Canvas.Left vào nút. Điều này hoạt động giống như một sự quyến rũ, và nút được đặt 500 pixel từ bên trái của ItemsControl bên trái. Tuyệt quá!

Tuy nhiên, Khi tôi đang xác định một ItemsSource ràng buộc vào một danh sách, các Canvas.Left không có bất kỳ tác dụng:

<ItemsControl ItemsSource="{Binding Elements}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Canvas IsItemsHost="True" /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Button Canvas.Left="500" Content="Button Text" /> 
     </DataTemplate>  
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

Bằng cách kiểm tra tình hình ứng dụng trong thời gian chạy, tôi thấy một sự khác biệt. Vùng chứa ContentPresenter đã được thêm giữa Canvas và nút ..

Làm cách nào tôi có thể đặt thuộc tính Canvas.Left trên chính ContentPresenter? Hoặc là có một cách khác để giải quyết vấn đề này?

Nhờ tất cả!

Trả lời

3

có một số giải pháp đến tâm trí của tôi:

  1. sử dụng một bố cục/rendertransform thay vì tài sản gắn liền
  2. lề sử dụng thay vì các tài sản gắn liền
  3. xuất phát từ ItemsControl, và thay đổi hành vi cách các thùng chứa con được tạo ra. (GetContainerForItemOverride, IsItemItsOwnContainerOverride). Bài viết này được giải thích khá độc đáo như thế nào nó hoạt động: http://drwpf.com/blog/2008/07/20/itemscontrol-g-is-for-generator/
25

Có thể thiết lập thuộc tính Canvas.Left sử dụng ItemContainerStyle:

<ItemsControl ItemsSource="{Binding Elements}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <Canvas IsItemsHost="True" /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Button Content="Button Text" /> 
      </DataTemplate>  
     </ItemsControl.ItemTemplate> 
    <ItemsControl.ItemContainerStyle> 
     <Style> 
      <Setter Property="Canvas.Left" Value="500" /> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
</ItemsControl> 
+0

Có vẻ lạ nhưng điều này làm việc cho tôi. – bryanbcook

+1

Bạn cũng có thể ràng buộc giá trị trong ItemContainerStyle và nó sẽ sử dụng cùng một mục với DataTemplate dùng làm nguồn. :-) –

+0

Bạn là anh hùng của tôi hôm nay. Cảm ơn bạn. –

2

Nút Không có một "Canvas" tài sản, vì vậy những gì bạn đang làm là thực hiện cuộc gọi tương đối với điều khiển lưu trữ, tuy nhiên vì mục và canvas nằm trong các Mẫu khác nhau nên không có liên kết trực tiếp, vì Canvas.Left này là vô nghĩa trước khi chạy.

do đó phương pháp của bạn không thể tìm thấy một thiết lập bên trái để mất thay đổi.

Tuy nhiên Setters chỉ được thực hiện trong thời gian chạy để

<Setter Property="Canvas.Left" Value="500" /> 

sẽ chỉ chạy sau khi các đối tượng đã được tạo ra và do đó không có một mối quan hệ tương đối.

Nếu không, bạn có thể sử dụng lề không thuộc đối tượng nút nhưng một lần nữa chỉ được diễn giải tại thời gian chạy