2009-10-28 40 views
22

Tôi hiện đang làm việc trong một điều khiển người dùng WPF (phần tử gốc của tệp XAML của tôi là "UserControl"), mà tôi biết đang được lưu trữ bên trong một Cửa sổ. Làm cách nào để truy cập thuộc tính của Cửa sổ bằng cách sử dụng ràng buộc dữ liệu?"RelativeSource FindAncestor" của WPF Data Binding chính xác là gì?

Có ai biết tại sao chỉ đơn giản

<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}" Path="..." /> 

không hoạt động? Thông báo lỗi tôi nhận được là:

System.Windows.Data Cảnh báo: 4: Không tìm thấy nguồn để liên kết với tham chiếu 'RelativeSource FindAncestor, AncestorType =' System.Windows.Window ', AncestorLevel =' 1 ''.

Chỉnh sửa: Tôi đã kết thúc bằng cách sử dụng một biến thể về cách tiếp cận của ArsenMkrt, vì vậy đã chấp nhận câu trả lời của mình. Tuy nhiên, tôi vẫn quan tâm đến việc tìm ra lý do tại sao FindAncestor không "chỉ làm việc".

+2

bạn nói bạn đã thay đổi câu trả lời của mình, bạn có thể đăng những gì bạn thực sự đã làm không? – Miles

+0

Lưu ý rằng tôi đang tìm kiếm giải pháp cho vấn đề này trong ngữ cảnh của mẫu MVVM. Thuộc tính của Cửa sổ mà tôi muốn liên kết với thực sự là một thuộc tính của ViewModel của Window. – user200783

+1

ArsenMkrt đã đề xuất tạo thuộc tính trong UserControl và liên kết với điều đó, sau đó đến lượt (trong XAML) ràng buộc thuộc tính này với thuộc tính mong muốn của Cửa sổ. Tuy nhiên, với mẫu MVVM, UserControl không bao giờ xuất hiện trong XAML, do đó phần thứ hai là không thể. – user200783

Trả lời

15

Cách tốt nhất là để đặt tên cho UserControl

Tạo phụ thuộc myProperty tài sản trong UserControl với hai cách ràng buộc và ràng buộc nó trong cửa sổ chính, hơn ràng buộc trong UserControl như thế này

<UserControl x:Name = "myControl"> 
    <Label Content={Binding ElementName= myControl, Path=MyProperty}/> 
</UserControl> 
+0

Nhưng tôi muốn liên kết với một thuộc tính trên cửa sổ chứa (được định nghĩa trong một tệp XAML khác), chứ không phải trên UserControl. – user200783

+0

Hơn nữa, sẽ tốt hơn nếu có thuộc tính trong điều khiển người dùng và liên kết thuộc tính đó với thuộc tính của cửa sổ –

+2

Bạn có thể tạo thuộc tính phụ thuộc trong UserControl không? bạn không thêm usercontrol trong cửa sổ?

0

I Think bạn nên thiết lập chế độ = "OneWayToSource" như thế này:

<TextBox Text="{Binding RelativeSource={RelativeSource FindAncestor ,AncestorType={x:Type Grid}},Path=BackGround , Mode=OneWayToSource , UpdateSourceTrigger = PropertyChanged}" /> 
4

Nếu bạn đang cố gắng để 'thoát' khỏi một ItemsControl hoặc DataGridView để đến một số Window bạn có thể thấy rằng AncestorType của x:Type Window không hoạt động. Hoặc ít nhất dường như không ...

Nếu đây là trường hợp bạn có thể chạy Blend hoặc Visual Studio và mong đợi dữ liệu hiển thị trong thời gian thiết kế - điều đó sẽ không vì VS + Blend cả hai tạo ra các cá thể riêng của họ không thực sự là Windows. Nó sẽ làm việc trong thời gian chạy tốt, nhưng không phải trong chế độ thiết kế.

Có một vài điều bạn có thể làm:

  • Bọc trong một usercontrol

  • Dưới đây là một giải pháp thay thế tôi đã đi lên với. Có một lợi thế là bạn không tham chiếu trực tiếp UserControl hoặc Window, vì vậy nếu bạn thay đổi vùng chứa mẹ, mã của bạn sẽ không bị hỏng.

    <Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:views="clr-namespace:MyWPFApplication.Views" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     
    x:Class="MyWPFApplication.Views.UPCLabelPrinterWindow" 
    mc:Ignorable="d" 
    x:Name="LayoutRoot" 
    Title="UPCLabelPrinterWindow"> 
    
    <views:DataContextWrapper> 
        <DockPanel> 
         ... 
        </DockPanel> 
    </views:DataContextWrapper> 
    

đâu DataContextWrapper chỉ là một Lưới

namespace MyWPFApplication.Views { 
    public class DataContextWrapper : Grid 
    { 

    } 
} 

Sau đó, khi bạn ràng buộc bạn làm điều này:

<TextBlock Text="{Binding="{Binding DataContext.SomeText, 
    RelativeSource={RelativeSource AncestorType={x:Type views:DataContextWrapper}, 
    Mode=FindAncestor}}" /> 

Lưu ý: nếu bạn muốn liên kết với một tài sản trên cửa sổ chính nó là phức tạp hơn và bạn có lẽ nên liên kết thông qua một thuộc tính phụ thuộc hoặc một cái gì đó như thế. Nhưng nếu bạn đang sử dụng MVVM thì đây là một giải pháp tôi tìm thấy.

+0

Trong trường hợp của tôi 'AncestorType = {x: Type Window}' khá hữu ích, bởi vì 'AncestorType = UserControl' bằng cách nào đó không trỏ đến cửa sổ của tôi - mặc dù nó thường làm. – LuckyLikey