Nếu bạn đang sử dụng MVVM đúng thì nhấp vào nút OK của bạn phải được xử lý bởi một số Command
. Lệnh này phải đến từ ViewModel
của bạn. Các thuộc tính ràng buộc Expliticly
phải đến từ ViewModel
của bạn một lần nữa. Vì vậy, những gì ngăn cản bạn.
- Không sử dụng
Explicit
ràng buộc nhưng sử dụng ràng buộc OneWay
.
- Trong nút của bạn, hãy liên kết lệnh và liên kết tham số lệnh với thuộc tính Phụ thuộc ràng buộc
OneWay
.
- Trong trình xử lý Execute của Command (phải là một phương thức nào đó từ ViewModel của bạn), thay đổi thuộc tính của ViewModel bằng tham số sắp tới.
- Tăng số
NotifyPropertyChanged
cho thuộc tính đó từ ViewModel
của bạn.
Ví dụ:
Giả sử tôi cần cập nhật văn bản của TextBox trở lại mô hình của tôi khi nhấp vào nút OK.
Vì vậy, tôi có lớp EmployeeViewModel
có thuộc tính EmployeeName
trong đó. Nơi nghỉ này có quầy thu đổi và người đặt đồ. Các setter tăng tài sản thay đổi thông báo. Mô hình khung nhìn cũng có một thuộc tính khác của loại ICommand
có tên SaveNameCommand
trả về một lệnh cho tôi thực hiện.
EmployeeViewModel
là loại ngữ cảnh dữ liệu của chế độ xem của tôi. Myview có một số TextBox
(được đặt tên là x: Name = "EmployeeNameTxBx") OneWay
được liên kết với EmployeeName
và một Nút là OK
. Tôi liên kết tài sản Button.Command
với tài sản EmployeeViewModel.SaveNameCommand
và Button.CommandParameter
bị ràng buộc với thuộc tính EmployeeNameTxBx.Text
.
<StackPanel>
<TextBox x:Name="EmployeeNameTxBx"
Text="{Binding EmployeeName, Mode=OneWay}" />
<Button Content="OK"
Command="{Binding SaveNameCommand}"
CommandParameter="{Bidning Text, ElementName=EmployeeNameTxBx}" />
</StackPanel>
Bên EmployeeViewModel
của tôi, tôi có OnSaveNameCommandExecute(object param)
phương pháp để thực hiện SaveNameCommand
tôi.
Trong này thực hiện mã này ...
var text = (string)param;
this.EmployeeName = text;
Bằng cách này CHỈ OK nút nhấp chuột, cập nhật văn bản của TextBox trở lại vào EmployeeName
tài sản của mô hình.
EDIT
Nhìn vào ý kiến của bạn dưới đây, tôi thấy rằng bạn đang cố gắng để thực hiện Validation trên một giao diện người dùng. Bây giờ điều này thay đổi mọi thứ một chút.
IDataErrorInfo
và xác thực có liên quan hoạt động CHỈ NẾU các điều khiển nhập của bạn (chẳng hạn như Hộp văn bản) là HaiWay bị ràng buộc. Vâng đó là cách nó được dự định. Vì vậy, bây giờ bạn có thể hỏi "Liệu điều này có nghĩa là toàn bộ khái niệm KHÔNG cho phép dữ liệu không hợp lệ chuyển sang mô hình là vô ích trong MVVM nếu chúng ta sử dụng IDataErrorInfo"?
Không thực sự!
Xem MVVM không thực thi quy tắc CHỈ dữ liệu hợp lệ sẽ trở lại. Nó chấp nhận dữ liệu không hợp lệ và đó là cách hoạt động của IDataErrorInfo
và làm tăng các thông báo lỗi. Vấn đề là ViewModel chỉ là softcopy Chế độ xem của bạn để có thể là bẩn. Điều cần đảm bảo là độ bẩn này không phải là cam kết với các giao diện bên ngoài của bạn như dịch vụ hoặc cơ sở dữ liệu.
Luồng dữ liệu không hợp lệ như vậy nên bị hạn chế bởi ViewModel
bằng cách kiểm tra dữ liệu không hợp lệ. Và dữ liệu đó sẽ đến nếu chúng tôi đã bật tính năng ràng buộc TwoWay
. Vì vậy, xem xét rằng bạn đang thực hiện IDataErrorInfo
sau đó bạn cần phải có TwoWay
ràng buộc đó là hoàn toàn cho phép trong MVVM.
Cách tiếp cận 1:
gì nếu tôi wan để xác nhận một cách rõ ràng các mục nhất định về giao diện người dùng trên nút bấm?
Để sử dụng thủ thuật xác thực bị trì hoãn này. Trong ViewModel của bạn có một lá cờ được gọi là isValidating. Đặt mặc định là false.
Trong tài sản IDataErrorInfo.this
bạn bỏ qua xác nhận bằng cách kiểm tra isValidating cờ ...
string IDataErrorInfo.this[string columnName]
{
get
{
if (!isValidating) return string.Empty;
string result = string.Empty;
bool value = false;
if (columnName == "EmployeeName")
{
if (string.IsNullOrEmpty(AccountType))
{
result = "EmployeeName cannot be empty!";
value = true;
}
}
return result;
}
}
Sau đó, trong lệnh OK bạn thực hiện xử lý, kiểm tra tên nhân viên và sau đó nâng cao sự kiện thay đổi sở hữu thông báo cho các tài sản tương tự ...
private void OnSaveNameCommandExecute(object param)
{
isValidating = true;
this.NotifyPropertyChanged("EmployeeName");
isValidating = false;
}
Điều này kích hoạt xác thực CHỈ khi bạn nhấp OK. Hãy nhớ rằng EmployeeName
sẽ CÓ chứa dữ liệu không hợp lệ để xác thực hoạt động.
Phương pháp 2:
gì nếu tôi muốn cập nhật một cách rõ ràng ràng buộc không có chế độ TwoWay trong MVVM?
Sau đó, bạn sẽ phải sử dụng Attached Behavior
. Hành vi sẽ đính kèm vào nút OK và sẽ chấp nhận danh sách tất cả các mục cần được làm mới các liên kết của chúng.
<Button Content="OK">
<local:SpecialBindingBehavior.DependentControls>
<MultiBinding Converter="{StaticResource ListMaker}">
<Binding ElementName="EmployeeNameTxBx" />
<Binding ElementName="EmployeeSalaryTxBx" />
....
<MultiBinding>
</local:SpecialBindingBehavior.DependentControls>
</Button>
Các ListMaker
là một IMultiValueConverter
mà chỉ đơn giản chuyển đổi giá trị vào một danh sách ...
Convert(object[] values, ...)
{
return values.ToList();
}
Trong SpecialBindingBehavior
của bạn có một tài sản thay đổi DependentControls
xử lý ...
private static void OnDependentControlsChanged(
DependencyObject depObj,
DependencyPropertyChangedEventArgs e)
{
var button = sender as Button;
if (button != null && e.NewValue is IList)
{
button.Click
+= new RoutedEventHandler(
(object s, RoutedEventArgs args) =>
{
foreach(var element in (IList)e.NewValue)
{
var bndExp
= ((TextBox)element).GetBindingExpression(
((TextBox)element).Textproperty);
bndExp.UpdateSource();
}
});
}
}
Nhưng tôi vẫn sẽ đề nghị bạn sử dụng trước MVVM tinh khiết của tôi dựa ** Cách tiếp cận 1.
lời cảm ơn đầu tiên cho câu trả lời chi tiết của bạn! và trở lại vấn đề của tôi, tôi đang sử dụng mvvm tinh khiết và tôi có lệnh trong vm của tôi và tôi đang sử dụng NotifyPropertyChanged. nhưng nếu tôi sử dụng OneWay ràng buộc và tôi có trong cửa sổ 10 textboxes của nó có nghĩa là tôi cần phải gửi trong các tham số lệnh 10 tên phần tử? và sau đó cập nhật chúng theo cách thủ công? không có cách nào để sử dụng ToWay ràng buộc? – Maya
cũng ngay bây giờ tôi đang sử dụng IDataError để xác nhận văn bản trong hộp văn bản, nếu tôi sẽ sử dụng OneWay ràng buộc tôi vẫn có thể xác nhận văn bản? – Maya
@Maya vui lòng xem mũi của tôi đã chỉnh sửa ở trên. –