2010-02-21 36 views
13

Tôi đang gặp sự cố khi databinding thuộc tính TextBox.Text đến phương thức của đối tượng. Ý tưởng này cho phép người dùng viết một tên tệp TextBox và sau đó có một phần mở rộng của tệp là TextBlock.Databinding vào một phương pháp trong WPF

class GetFileInfo 
{ 
    public string GetFileExtension(string fileName) 
    { 
     return Path.GetExtension(fileName); 
    } 
} 

Đây là XAML của tôi:

<Window.Resources> 
    <ObjectDataProvider x:Key="getFileInfo" MethodName="GetFileExtension" ObjectType="{x:Type local:GetFileInfo}"> 
     <ObjectDataProvider.MethodParameters> 
      <sys:String>abc.text</sys:String> 
     </ObjectDataProvider.MethodParameters> 
    </ObjectDataProvider> 
</Window.Resources> 

<StackPanel> 
    <TextBox Name="textBox1"> 
     <TextBox.Text> 
      <Binding Source="{StaticResource getFileInfo}" Path="MethodParameters[0]" BindsDirectlyToSource="True" UpdateSourceTrigger="PropertyChanged" /> 
     </TextBox.Text> 
    </TextBox> 
    <TextBlock Name="textBlock1" Text="{Binding Source={StaticResource getFileInfo}}"/> 
</StackPanel> 

Đối với một số lý do nó không được làm bất cứ điều gì. Anyknow có thể chỉ ra những gì có thể là lý do? Đây là những gì tôi nhìn thấy trên các thiết kế và khi tôi chạy các ứng dụng:

alt text http://img64.imageshack.us/img64/6922/f0rki14feo3oa3groxm5kgm.png

Và đây là những gì sẽ xảy ra khi tôi cố gắng thiết lập văn bản khác tại thời gian chạy:

alt text http://img684.imageshack.us/img684/1057/b52pnq1dm4i23qivizvpaqq.png Đây là lỗi do trình gỡ lỗi đưa ra khi cố gắng đặt văn bản khác tại thời gian chạy:

System.Windows.Data Error: 8 : Cannot save value from target back to source. BindingExpression:Path=MethodParameters[0]; DataItem='ObjectDataProvider' (HashCode=2207369); target element is 'TextBox' (Name='textBox1'); target property is 'Text' (type 'String') ArgumentException:'System.ArgumentException: Object of type 'MS.Internal.Data.PropertyPathWorker+IListIndexerArg' cannot be converted to type 'System.Int32'. at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast) at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr) at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture) at MS.Internal.Data.PropertyPathWorker.SetValue(Object item, Object value) at MS.Internal.Data.ClrBindingWorker.UpdateValue(Object value) at System.Windows.Data.BindingExpression.UpdateSource(Object value)'

+0

Bạn phải thay đổi ý tưởng từ ràng buộc Phương pháp thành thuộc tính. và tìm hiểu khái niệm về INotifyPropertyChanged & DataContext. Google một số mẫu MVVM quá. –

+4

+1 để đặt câu hỏi sẽ giúp nhiều người không hiểu dữ liệu. –

Trả lời

0

Ok , có vẻ như đây là lỗi khi chạy WPF 4.0, như có thể thấy trong các ý kiến ​​here.

Woops, I was a bit hasty .. the example works perfectly as long you compile it for the 3.5 framework (in VS 2010). But if you convert it to WPF 4.0 project the method WeightOnPlanet on ObjectDataProvider is nolonger invoked on odp2 when you edit the textbox. I have tried to find any new Attributes on either the Binding or the ObjectDataProvider – but nothing has worked out so far …

Khi biên dịch trong 3.5, nó hoạt động tốt ở đây.

0

Có phải là DataContext được đặt không? Trong code-behind của bạn, bạn đã đặt giá trị cho số TextBlock thành "saadsas" (tôi chỉ có thể đoán), đã phá vỡ dữ liệu của bạn?

+0

Tôi đã chỉnh sửa bài đăng gốc của mình. Về cơ bản tất cả mọi thứ tôi đã viết trong các tập tin mã của tôi là có. Tôi không đặt DataContext. Trong thực tế, im googling ngay bây giờ những gì một DataContext là. –

1

Databinding yêu cầu sự kiện NotifyPropertyChanged được gọi khi nguồn được cập nhật. Trong trường hợp này, bạn muốn quấn gọi chức năng này trong một get/set như vậy:

 


public class FileWrapper: System.ComponentModel.INotifyPropertyChanged{ 
    private string m_filename; 

    public string FileExtension{ 
     get{ return GetFileExtension(FileName);} 
    } 

    public string FileName{ 
     get{ return m_filename;} 
     set{ m_filename = value; OnPropertyChanged("FileName"); OnPropertyChanged("FileExtension"); 
    } 

    public string GetFileExtension(string filename){ 
     //implementation 
    } 

    public event System.ComponentModel.NotifyPropertyChangedEvent PropertyChanged = (a,b)=>{}; 

    protected void OnPropertyChanged(string property){ 
     PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(property)); 
    } 
} 
 
+0

Tôi sẽ thử mã này. Nhưng không phải là có một giải pháp đơn giản để chỉ chạy một số phương pháp từ một lớp học nhất định đưa ra một số thông số? –

+2

@devoured, Nếu bạn thích làm theo đúng cách WPF, đây sẽ là mã bạn cần sử dụng. Không có gì điên rồ xảy ra trong đoạn mã trên, nếu bạn biết điều này nó sẽ giúp bạn mãi mãi với WPF. trong bất kỳ MVVM dựa trên WPF bạn có thể thấy đoạn mã nhỏ này. Vì vậy, nó đáng để học. –

+0

Tôi thấy quan điểm của bạn. Tôi sẽ học nó theo cách này. –

2

Hình như bạn cần để có được một sự hiểu biết về MVVM, kiểm tra bài viết cổ điển này http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

+0

Có, nhưng như được nêu trong bài đăng của tôi, ý tưởng là nhập nội dung bạn muốn vào hộp văn bản vào thời gian chạy. Tôi biết rằng nó đang làm những gì anh ta nên với chuỗi Tôi đang cho anh ta vào thời gian thiết kế bên trong các thẻ . –

8

Mặc dù có thể sử dụng Binding để gọi phương thức và nhận giá trị trả về của nó, nhưng không đơn giản. Đó là nhiều đơn giản hơn để liên kết với các thuộc tính và sử dụng kết hợp thông báo ràng buộc và thay đổi để có được kết quả bạn đang tìm kiếm.

Tạo lớp học với hai thuộc tính, FilenameExtension. Filename chỉ là thuộc tính chuỗi đọc/ghi. Extension là thuộc tính chuỗi chỉ đọc mà getter gọi phương thức mà bạn đang cố gắng gọi.

Bây giờ, hãy làm cho lớp đó triển khai INotifyPropertyChanged, bởi vì nếu một thuộc tính có thể thay đổi mã, nó cần một cách để nói ràng buộc rằng nó đã làm như vậy. Đặt bộ phận của thuộc tính Filename thông báo ràng buộc rằng thuộc tính Extension đã thay đổi.

Thêm Binding vào số TextBox liên kết với thuộc tính Filename bằng chế độ TwoWay. Thêm Binding vào số TextBox liên kết với Extension bằng chế độ mặc định OneWay.

Chuỗi sự kiện là:

  1. loại tài khoản mới Filename thành một ràng buộc TextBox và nhấn TAB.
  2. Các TextBox mất tiêu điểm.
  3. Bởi vì chế độ BindingTwoWay và sử dụng hành vi mặc định cập nhật nguồn khi mục tiêu mất tiêu điểm, đó là những gì nó làm.
  4. Binding cập nhật nguồn bằng cách gọi số Filename thiết lập.
  5. Thiết lập Filename đặt ra PropertyChanged.
  6. Binding xử lý PropertyChanged, xem xét đối số của nó và thấy rằng thuộc tính Extension đã thay đổi.
  7. Số Binding gọi số Extension của tài sản getter.
  8. Extension getter của tài sản gọi phương thức để xác định tiện ích mở rộng cho Filename và trả về số này Binding.
  9. Binding cập nhật mục tiêu TextBox với giá trị mới Extension.

Đây là khái niệm cốt lõi bên dưới ràng buộc dữ liệu và mẫu MVVM. Một khi bạn hiểu nó, nó trở thành bản chất thứ hai, và phát triển WPF trở nên dễ dàng hơn khoảng mười triệu lần.

+0

Tôi đang sử dụng Sam's Teach Yourself WPF trong 24 giờ ebook và ive học tấn cho đến nay và im ony trên chương 6 (chương databinding) bởi đến nay một trong những cách dễ nhất để tìm hiểu WPF. Tôi đã dành hàng giờ tìm kiếm các nguồn tài nguyên trực tuyến và cuốn sách này là đến nay là ive tốt nhất được tìm thấy cho người mới bắt đầu WPF. :) –

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