2010-09-08 28 views
25

Tôi đang làm gì sai ở đây ?:RelativeSource ràng buộc từ một ToolTip hoặc ContextMenu

<GridViewColumn> 
    <GridViewColumn.CellTemplate> 
     <DataTemplate> 
      <Button> 
      <Button.ToolTip> 
       <TextBlock Text="{Binding Path=Title, RelativeSource={RelativeSource AncestorType=Window}}" /> 

Đó chỉ là một ví dụ đơn giản, điều đó không làm việc anyway :) Thật sự tôi cần để có được một giá trị từ tài sản khác nằm trong phạm vi của DataContext của Window.

Giúp tôi xin.

Trả lời

63

Điều này là khó khăn vì ToolTip không phải là một phần của VisualTree. Here bạn thấy một giải pháp tuyệt vời cho cùng một vấn đề với ContextMenus. Cũng giống như cách bạn có thể sử dụng ToolTip.

CẬP NHẬT
Rất tiếc, liên kết đã biến mất và tôi không tìm thấy bài viết được tham chiếu nữa.
Theo như tôi nhớ, blog được tham chiếu đã chỉ ra cách liên kết với một DataContext của một VisualTree khác, thường là cần thiết khi ràng buộc từ một ToolTip, một ContextMenu hoặc một Popup.

Một cách hay để làm điều này, là cung cấp ví dụ mong muốn (ví dụ: ViewModel) trong thuộc tính Thẻ của Mục tiêu vị trí. Ví dụ sau thực hiện điều này để truy cập vào một lệnh sơ thẩm của một ViewModel:

<Button Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=Self}}"> 
    <Button.ContextMenu> 
    <ContextMenu> 
     <MenuItem Command="{Binding PlacementTarget.Tag.DesiredCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" .../> 
    <ContextMenu> 
    </Button.ContextMenu> 
</Button> 

tôi đã không kiểm tra nó và một thời gian dài của nó tôi đã làm điều này lần cuối cùng. Hãy bình luận nếu nó không hoạt động cho bạn.

UPDATE 2

Khi liên kết ban đầu mà câu trả lời này đã được viết về đã biến mất, tôi nhấn archive.org và found the original blog entry. Dưới đây là, đúng nguyên văn từ blog:

Bởi vì một ContextMenu trong WPF không tồn tại trong cây thị giác của trang/cửa sổ/kiểm soát của bạn cho mỗi gia nhập, dữ liệu ràng buộc có thể là một chút khó khăn. Tôi đã tìm kiếm cao và thấp trên web cho điều này, và hầu hết các câu trả lời phổ biến nhất có vẻ là "chỉ cần làm điều đó trong mã phía sau". SAI RỒI! Tôi không đến với thế giới tuyệt vời của XAML để trở lại làm những việc trong mã phía sau.

Đây là ví dụ của tôi về điều đó sẽ cho phép bạn liên kết với chuỗi mà tồn tại dưới dạng thuộc tính của cửa sổ của bạn.

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     MyString = "Here is my string"; 
    } 

    public string MyString 
    { 
     get; 
     set; 

    } 
} 


<Button Content="Test Button" 
    Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"> 
    <Button.ContextMenu> 
    <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, 
      RelativeSource={RelativeSource Self}}" > 
     <MenuItem Header="{Binding MyString}"/> 
    </ContextMenu> 
    </Button.ContextMenu> 
</Button> 

Phần quan trọng là Thẻ trên nút (mặc dù bạn có thể chỉ cần dễ dàng đặt DataContext của nút). Cửa hàng này tham chiếu đến cửa sổ chính. ContextMenu có khả năng truy cập vào số này thông qua thuộc tính PlacementTarget của nó. Sau đó, bạn có thể chuyển ngữ cảnh này xuống qua các mục menu của bạn.

Tôi thừa nhận đây không phải là giải pháp thanh lịch nhất trên thế giới. Tuy nhiên, nó đánh bại các công cụ thiết lập trong mã phía sau. Nếu có ai đó có số thậm chí tốt hơn để thực hiện việc này, tôi muốn nghe điều đó.

+0

Đây là nó! Cảm ơn bạn! – Agzam

+0

Liên kết đó đã chết. Bạn có thể điền thông tin còn thiếu không? –

+1

@Bill Tôi chưa tìm thấy liên kết nữa nhưng tôi đã cố gắng giải thích cách thức giải quyết vấn đề. – HCL

-2

Tôi nghĩ rằng nó nên được thực hiện như thế này:

{Binding Path=Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" 
+0

Không ... không hoạt động. Tôi đã thử rằng một trong những đã ... – Agzam

+0

Điều này hoạt động không phải vì VisualTree chính không có sẵn từ ToolTip. Xem câu trả lời của tôi. – HCL

+0

yah xin lỗi, thậm chí không thực sự nhận thấy rằng nó nằm trong một tooltip. – mdm20

0

ContextMenu không có trong cây thị giác, ràng buộc sẽ không hoạt động. giải pháp đơn giản là sử dụng Mẫu proxy, bạn có thể tạo lớp bao bọc thừa kế từ DependencyObject và có DependencyProperty sẽ giữ DataContext trong số Window, sau đó bạn có thể có tài nguyên proxy trong XAML và cuối cùng ràng buộc lệnh MenuItem của bạn lệnh mong muốn của bạn thông qua đối tượng proxy.
mẫu Proxy:

Public class ProxyClass : DependencyObject 
{ 
    Public object Data {get; set;} 
    public static readonly DependencyProperty DataProperty = DependencyProperty.Register("DataProperty", typeof(object), typeof(ProxyClass), new FrameworkPropertyMetadata(null)); 

} 

Làm thế nào để sử dụng trong XAML:

<Window DataContext="{Binding MyViewModel}"> 
... 
<Window.Resources> 
    <ProxyClass Data={Binding} x:Key="BindingProxy"/> 

</Window.Resources> 
... 
<MenuItem Command="{Binding Source={StaticResource BindingProxy}, Path=Data.MyDesiredCommand"/> 
... 
</Window> 

gì đang xảy ra?
Data thuộc tính của ProxyClass sẽ liên kết với DataContext của Window, sau đó nó có tất cả các comamnd và thuộc tính của bạn ViewModel bên trong tài nguyên ProxyClass.
một lợi ích khác của phương pháp này là tính di động và tái sử dụng trong nhiều lượt xem và dự án.

2

Mỗi bên dưới:
Vị trí Mục tiêu là điều khiển sở hữu ContextMenu (ví dụ: DataGrid). Không cần một thuộc tính "thẻ".

IsEnabled liên kết với giá trị "myProperty" của DataGrid.

Tôi đã thử nghiệm tính năng này và hoạt động. Đã có vấn đề tương tự với ràng buộc.

<ContextMenu 
DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}" 
IsEnabled="{Binding myProperty}" 
> 
Các vấn đề liên quan