2012-07-04 14 views
6

này có vẻ là một chủ đề khá phổ biến, nhưng ...Làm thế nào để truy cập một điều khiển từ một menuitem ContextMenu thông qua cây thị giác?

Tôi có XAML sau:

<internal:MyCommandObject x:Name="CommandModel"/> 

<Button DockPanel.Dock="Bottom" Command="{Binding DoAction, ElementName=CommandModel}"> 
    <Button.ContextMenu> 
     <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> 
      <MenuItem Command="{Binding DoAction, ElementName=CommandModel}"/> 
     </ContextMenu> 
    </Button.ContextMenu> 
    Click Me 
</Button> 

Bây giờ, MyCommandObject là một điều khiển mà exposes lệnh động từ DataContext của nó. Bạn biết điều gì sẽ xảy ra tiếp theo. :)

Về cơ bản, lệnh nút hoạt động hoàn hảo - khi tôi nhấp vào, lệnh DoAction trên MyCommandObject được thực thi hoàn hảo. Tuy nhiên, lệnh trong menuitem không được thực thi. Tôi đã thử các thủ thuật khác nhau như thiết lập menu ngữ cảnh datacontext thành placementTarget để nó có thể duyệt qua cây trực quan của các điều khiển và vân vân, nhưng không có gì làm.

Điều chỉnh cụ thể của RelativeSourceCommandTarget rune nào tôi có cần phải thực hiện việc này?

Trả lời

4

này đang xảy ra vì DataContext="{Binding PlacementTarget,... ràng buộc sẽ thiết lập các nút như MenuItems DataContext nhưng điều đó sẽ không thêm ContextMenu đến VisualTree của cửa sổ của bạn và đó là lý do tại sao ElementName của ràng buộc sẽ không hoạt động. Một cách giải quyết đơn giản để sử dụng ElementName bindings là để thêm video này trong cửa sổ của bạn/UserControl của code-behind:

NameScope.SetNameScope(contextMenuName, NameScope.GetNameScope(this)); 

giải pháp khác là để làm điều này -

<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> 
    <MenuItem Command="{Binding DataContext.DoAction}"/> 
</ContextMenu> 

DataContext="{Binding PlacementTarget,... sẽ thiết lập các nút (Placementtarget) như DataContext của ContextMenu của bạn, vì vậy bạn có thể sử dụng DataContext của nút để liên kết lệnh.

Cập nhật:

Bạn có thể thử và sử dụng NameScope.NameScope Attached Property thiết NameScope trong XAML nhưng tôi không chắc chắn làm thế nào bạn sẽ nhận được NameScope của cửa sổ cha mẹ mà không cần mã!

Bạn sẽ phải làm điều gì đó tương tự như bài viết sau đây của Josh Smith, ông cung cấp một cách để làm điều này trong XAML; nhưng điều đó quá liên quan đến mã (hơn sau đó dòng mã) -

Enable ElementName Bindings with ElementSpy

Bất kỳ lý do cụ thể để không sử dụng dòng mã này?

+0

Cảm ơn vì điều này. Tôi đang cố gắng không sử dụng code-behind nếu có thể - có thể xác định NameScope trong XAML không? Thật không may, tôi không thể đặt ngữ cảnh dữ liệu của mục menu thành nút hiển thị lệnh. Đây là một menu ngữ cảnh cho một lưới, và tôi cần DataContext của mục đã chọn để tôi có thể chuyển các thuộc tính từ đó như các tham số cho lệnh. – Webreaper

+0

Lý do không sử dụng mã phía sau là xaml không được biên dịch - mọi thứ được thực hiện trong ứng dụng khách khi chạy bằng cách sử dụng kết buộc muộn. – Webreaper

+1

@Webreaper Bạn không chắc chắn liệu bạn đang nói về kịch bản của bạn hay trong genral, nhưng hầu hết các tệp XAML được biên dịch thành BAML tại thời điểm xây dựng (xem xaml của bạn cũng trông như vậy); Tôi sẽ đề nghị bạn giới thiệu các liên kết này - [Biên dịch XAML = BAML không phải IL] (http://blogs.microsoft.co.il/blogs/tomershamam/archive/2007/05/25/Compiled-XAML-\_3D00\_ -BAML-not-IL.aspx) và [B là dành cho ... BAML] (http://blogs.msdn.com/b/jimoneil/archive/2009/01/12/b-is-for-baml.aspx) – akjoshi