2008-09-29 42 views
28

Theo mô hình View-Model-ViewModel cho WPF, tôi đang cố gắng databind Heights và Width của các định nghĩa khác nhau cho các điều khiển lưới, vì vậy tôi có thể lưu trữ các giá trị mà người dùng đặt chúng sau khi sử dụng GridSplitter. Tuy nhiên, mô hình bình thường dường như không hoạt động đối với các đặc tính cụ thể này.Tôi làm cách nào để databind Chiều rộng của Chiều rộng hoặc Độ rộng của hàngDefID?

Lưu ý: Tôi đăng bài này dưới dạng câu hỏi tham chiếu mà tôi đăng khi Google không thành công và tôi phải tự mình làm việc này. Câu trả lời của riêng tôi để làm theo.

Trả lời

17

Đã có một số gotchas tôi phát hiện ra:

  1. Mặc dù nó có thể xuất hiện giống như một đôi trong XAML, giá trị thực tế cho Chiều cao một * Định nghĩa hoặc Width là một 'GridLength' struct.
  2. Tất cả các thuộc tính của GridLength đều chỉ đọc, bạn phải tạo một thuộc tính mới mỗi khi bạn thay đổi nó.
  3. Không giống như mọi thuộc tính khác trong WPF, Chiều rộng và Chiều cao không mặc định chế độ dữ liệu của chúng thành 'HaiWay', bạn phải tự thiết lập điều này.

thusly, tôi đã sử dụng đoạn mã sau:

private GridLength myHorizontalInputRegionSize = new GridLength(0, GridUnitType.Auto) 
public GridLength HorizontalInputRegionSize 
{ 
    get 
    { 
     // If not yet set, get the starting value from the DataModel 
     if (myHorizontalInputRegionSize.IsAuto) 
      myHorizontalInputRegionSize = new GridLength(ConnectionTabDefaultUIOptions.HorizontalInputRegionSize, GridUnitType.Pixel); 
     return myHorizontalInputRegionSize; 
    } 
    set 
    { 
     myHorizontalInputRegionSize = value; 
     if (ConnectionTabDefaultUIOptions.HorizontalInputRegionSize != myHorizontalInputRegionSize.Value) 
     { 
      // Set the value in the DataModel 
      ConnectionTabDefaultUIOptions.HorizontalInputRegionSize = value.Value; 
     } 
     OnPropertyChanged("HorizontalInputRegionSize"); 
    } 
} 

Và XAML:

<Grid.RowDefinitions> 
    <RowDefinition Height="*" MinHeight="100" /> 
    <RowDefinition Height="Auto" /> 
    <RowDefinition Height="{Binding Path=HorizontalInputRegionSize,Mode=TwoWay}" MinHeight="50" /> 
</Grid.RowDefinitions> 
+9

Dòng thời gian đặc trưng cho WPF, do đó không thuộc lớp ViewModel. –

+2

Tôi nghĩ rằng niềm tin "không có WPF trong ViewModel" là sai, vì WPF có rất nhiều cấu trúc liên quan đến mô hình MVVM, chẳng hạn như chính bản thân dữ liệu. Bạn có thể nói "GridLength là dành riêng cho VIEW", thay vào đó (trừ khi nó là một phần của vấn đề miền, chẳng hạn như trong các ứng dụng trực quan hóa dữ liệu mà rất có mục đích là bố cục và hiển thị mọi thứ). Nhưng chắc chắn nó gây tranh cãi ... – heltonbiker

+0

@heltonbiker "GridLength dành riêng cho VIEW" là chính xác hơn. trừ khi logic nghiệp vụ của bạn là một phần hoặc duy nhất về bố cục UI (thiết kế) –

4

Một khả năng khác, kể từ khi bạn lớn lên chuyển đổi giữa GridLengthint, là tạo ra một IValueConverter và sử dụng nó khi liên kết với Width. IValueConverter s cũng xử lý ràng buộc hai chiều vì chúng có cả phương thức ConvertTo()ConvertBack().

34

Tạo một IValueConverter như sau:

public class GridLengthConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     double val = (double)value; 
     GridLength gridLength = new GridLength(val); 

     return gridLength; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     GridLength val = (GridLength)value; 

     return val.Value; 
    } 
} 

Sau đó, bạn có thể sử dụng bộ chuyển đổi trong Ràng buộc của bạn:

<UserControl.Resources> 
    <local:GridLengthConverter x:Key="gridLengthConverter" /> 
</UserControl.Resources> 
... 
<ColumnDefinition Width="{Binding Path=LeftPanelWidth, 
            Mode=TwoWay, 
            Converter={StaticResource gridLengthConverter}}" /> 
+0

Nếu bạn tìm kiếm giải pháp cho vấn đề tương tự, bạn có thể tìm thấy nó ở đây: http://stackoverflow.com/questions/7660967/wpf-error-cannot -find-govering-frameworkelement-for-target-element – dzendras

+0

Wpf đã có một lớp GridLengthConverter. Nó sẽ có thể sử dụng nó như là? – heltonbiker

+4

@heltonbiker Thật không may, GridLengthConverter thực hiện ITypeConverter hơn là IValueConverter, và do đó không thể được sử dụng như là một chuyển đổi ràng buộc WPF. –

2

Giải pháp đơn giản nhất là chỉ cần sử dụng các thiết lập chuỗi cho các đặc tính này để WPF sẽ tự động hỗ trợ chúng bằng GridLengthConverter mà không cần thêm bất kỳ công việc nào.

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