2008-11-12 45 views
7

Tôi đang cố gắng gắn một DependancyProperty vào một trong các liên kết người dùng của tôi với thuộc tính Width của Column trong một Grid.Kết nối WPF với chiều rộng cột lưới

tôi có mã tương tự như sau:

<Grid x:Name="MyGridName"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition x:Name="TitleSection" Width="100" /> 
     <ColumnDefinition Width="*" /> 
    </Grid.ColumnDefinitions> 

    <Grid.RowDefinitions>...</Grid.RowDefinitions> 

    <GridSplitter x:Name="MyGridSplitter" Grid.Row="0" Grid.Column="0" ... /> 
</Grid> 

Trong một usercontrol riêng tôi có sau DependancyProperty xác định.

public static readonly DependencyProperty TitleWidthProperty = DependencyProperty.Register("TitleWidth", typeof(int), typeof(MyUserControl)); 

public int TitleWidth 
{ 
    get { return (int)base.GetValue(TitleWidthProperty); } 
    set { base.SetValue(TitleWidthProperty, value); } 
} 

tôi đang tạo ra thể hiện của các UserControl trong mã, vì vậy tôi có một tuyên bố ràng buộc tương tự như sau:

MyUserControl Cntrl = new MyUserControl(/* Construction Params */); 
BindingOperations.SetBinding(Cntrl , MyUserControl.AnotherProperty, new Binding { ElementName = "objZoomSlider", Path = new PropertyPath("Value"), Mode = BindingMode.OneWay }); 
BindingOperations.SetBinding(Cntrl , MyUserControl.TitleWidthProperty, new Binding { ElementName = "TitleSection", Path = new PropertyPath("ActualWidth"), Mode = BindingMode.OneWay }); 
/* Other operations on Cntrl */ 

Đầu tiên ràng buộc công trình quy định fantastically, mặc dù đó là ràng buộc để một UIElement thực tế (trong trường hợp này là Slider), nhưng Binding to "TitleSection" (là ColumnDefinition được định nghĩa trong Grid) không thành công. Đặt một breakpoint trong mã và làm một chiếc đồng hồ trên "TitleSection" trả về đối tượng mong đợi.

Tôi bắt đầu nghi ngờ rằng không thể ràng buộc ColumnDefinition x: Name'd. Có ai có thể đề xuất cách tôi có thể liên kết với chiều rộng thay đổi của cột đầu tiên trong lưới của tôi không?

EDIT # 1 - Để trả lời bình luận

Các databinding 'thất bại' theo nghĩa là với một breakpoint đặt trên setter cho TitleWidth bất động sản, và sử dụng điều khiển GridSplitter để thay đổi kích thước cột đầu tiên, breakpoint là không bao giờ trúng. Ngoài ra, mã tôi mong đợi sẽ được kích hoạt khi các thay đổi DependancyProperty TitleWidth không được thực hiện.

Bảng điều khiển người dùng đang được tạo và thêm vào Stackpanel trong lưới trong hàm Window_Loaded. Tôi hy vọng rằng Grid đã được render vào thời điểm các Usercontrol đang được xây dựng. Chắc chắn x: Name'd Element TitleSection có thể xem và có giá trị 100 khi chúng đang được xây dựng/trước khi sự ràng buộc xảy ra.

EDIT # 2 - Có thể có gì đó liên quan đến điều này?

Tôi đã có một sniff quanh các trang MSDN cho tài liệu Grid ColumnDefinition và đã đi qua GridLength() nhưng tôi không thể có được đầu của tôi xung quanh cách tôi có thể sử dụng điều này trong một biểu thức ràng buộc. Tôi không thể sử dụng GridLengthConverter liên quan như một công cụ chuyển đổi trong mã ràng buộc vì nó không lấy được từ IValueConverter.

Tôi nghiêng về phía nào đó liên kết với thuộc tính ActualWidth của một trong các ô trong đối tượng Lưới. Nó không có vẻ sạch sẽ như ràng buộc với định nghĩa cột, nhưng tại thời điểm này tôi không thể làm được điều đó.

+0

Không, tại sao bạn tạo usercontrol? Lưới đã được hiển thị chưa? – Donnelle

+0

Bạn không thể dựa vào thiết lập các điểm ngắt trong tập hợp/nhận của thuộc tính phụ thuộc, vì chúng sẽ không bao giờ được sử dụng bởi công cụ liên kết. Nội bộ depencency tài sản được thiết lập bằng cách sử dụng SetValue (DependencyProperty, giá trị) –

Trả lời

9

Vâng, tôi đã có một chút của một lao động kludge, tôi sẽ giải thích như thế nào cho các thế hệ tương lai:

Về cơ bản tôi có 2 cột, lưới hàng đa với quyền splitter liên kết trong cột đầu tiên để nó có thể được thay đổi kích thước bởi người dùng nếu nội dung nó chứa đòi hỏi nhiều không gian hơn. Để phức tạp những điều tôi có một điều khiển người dùng đang được tải một cách có lập trình vào một số hàng trong đó có một columnSpan của 2 cho mục đích rendering (nội dung 'chảy máu' từ một tế bào vào kế tiếp).

Khi cột đầu tiên được thay đổi kích thước, tôi cần điều này được phản ánh trong điều khiển người dùng. Trước hết tôi đã thử ràng buộc với ColumnDefinition nhưng nó thực sự không chơi bóng.

Làm thế nào tôi cố định/kludged nó

Trong một tế bào phụ tùng trong cột đầu tiên tôi đã thêm một <Label> với x: Name để làm cho nó dễ tiếp cận. Vì nó nằm trong một ô, nó có các thuộc tính mặc định là 'Stretch' và lấp đầy toàn bộ ô. Nó được thay đổi kích thước khi cột được thay đổi kích thước bằng cách sử dụng bộ chia. Liên kết với thuộc tính ActualWidth của Nhãn có nghĩa là các thay đổi đối với kích thước của cột được truyền đến DependancyProperty trong điều khiển người dùng columnSpanned của tôi một cách chính xác.

Suy nghĩ

Rõ ràng, mặc dù ColumnDefinition có một tài sản ActualWidth khi nó thay đổi nó không xuất hiện để bắn các sự kiện PropertyChanged nội bộ (hoặc thats đoán tốt nhất của tôi). Điều này có thể là một lỗi, hoặc theo thiết kế, nhưng đối với tôi nó có nghĩa là tôi đã phải sử dụng một giải pháp ít sạch hơn.

+1

Điều này làm việc tốt cho tôi. Tôi có một chút xoắn: Foredecker

3

Bạn đã thử thiết lập các ràng buộc trong xaml, sau đây sẽ làm việc cho bạn.

<ColumnDefinition 
    x:Name="TitleSection" 
    Width="{Binding 
       Path=TitleWidth, 
       RelativeSource={RelativeSource AncestorType=MyUserControl}}" 
    /> 

Nếu không, nhìn vào các mã liên kết mà bạn đã cung cấp, nó trông giống một cách sai lầm xung quanh với tôi, mục tiêu của các ràng buộc nên cột lưới và nguồn nên tài sản phụ thuộc của bạn.

Mã tương đương cho XAML trên là

BindingOperations.SetBinding(TitleSection, ColumnDefinition.WidthProperty, 
    new Binding() 
    { 
     RelativeSource= new RelativeSource(RelativeSourceMode.FindAncestor, typeof(MyUserControl),1), 
     Path = new PropertyPath("TitleWidth"), 
    }); 

Trên một lưu ý liên quan, sử dụng một GridSplitter và ràng buộc thuộc tính Width là mutally độc quyền. Ngay sau khi bạn thay đổi kích thước cột bằng cách sử dụng bộ tách, ràng buộc của bạn sẽ được thay thế bằng giá trị từ bộ tách.

Điều này tương tự như những gì bạn sẽ trải nghiệm bằng cách cập nhật bất kỳ thuộc tính nào là mục tiêu của ràng buộc. Khi bạn đặt giá trị đích trực tiếp trong mã, bạn sẽ thay thế đối tượng liên kết bằng giá trị mà bạn cung cấp.

2

ColumnDefinition.Width không phải là số nguyên - đó là một GridLength. Bạn không thể liên kết trực tiếp GridLength với Integer, bạn cần một công cụ chuyển đổi.

Đây cũng là lý do, tại sao bạn không thể liên kết bất kỳ thuộc tính Độ rộng của Điều khiển (gấp đôi) với thuộc tính Chiều rộng của Độ rộng Cột (GridLength) mà không có bộ chuyển đổi.

Các vấn đề liên quan