Si está utilizando MVVM realmente, su clic de botón Aceptar debe ser manejado por Command
. Este comando debe provenir de su ViewModel
. Las propiedades enlazadas Expliticly
deben provenir de su ViewModel
nuevamente. Entonces, ¿qué te detiene?
- No utilice
Explicit
vinculante pero el uso OneWay
vinculante.
- En su botón, enlace un comando y enlace un parámetro de comando a la propiedad Dependencia limitada
OneWay
.
- En el controlador Execute de su comando (que debe ser algún método de su ViewModel), cambie la propiedad de ViewModel con el parámetro que viene.
- Levante el
NotifyPropertyChanged
para esa propiedad de su ViewModel
.
E.g.
Supongamos que necesito actualizar el texto de un cuadro de texto en mi modelo con un clic en el botón Aceptar.
Así que para eso tengo una clase EmployeeViewModel
que tiene EmployeeName
propiedad en él. La propiedad tiene un getter y un setter. El colocador levanta la notificación de cambio de propiedad. El modelo de vista también tiene otra propiedad de tipo ICommand
llamada SaveNameCommand
que devuelve un comando para que la ejecute.
EmployeeViewModel
es el tipo de contexto de datos de mi vista. Myview tiene un TextBox
(denominado como x: Name = "EmployeeNameTxBx") OneWay
vinculado al EmployeeName
y un botón como OK
. Ato la propiedad Button.Command
a la propiedad EmployeeViewModel.SaveNameCommand
y Button.CommandParameter
a la propiedad EmployeeNameTxBx.Text
.
<StackPanel>
<TextBox x:Name="EmployeeNameTxBx"
Text="{Binding EmployeeName, Mode=OneWay}" />
<Button Content="OK"
Command="{Binding SaveNameCommand}"
CommandParameter="{Bidning Text, ElementName=EmployeeNameTxBx}" />
</StackPanel>
Dentro de mi EmployeeViewModel
que tienen OnSaveNameCommandExecute(object param)
método para ejecutar mi SaveNameCommand
.
En este realizar este código ...
var text = (string)param;
this.EmployeeName = text;
esta manera sólo botón OK clic, actualizaciones de texto del cuadro de texto de nuevo en el EmployeeName
propiedad del modelo.
EDITAR
En cuanto a sus comentarios abajo, veo que usted está tratando de implementar la validación de una interfaz de usuario. Ahora esto cambia las cosas un poco.
IDataErrorInfo
y la validación relacionada funciona SÓLO SI sus controles de entrada (como cuadros de texto) son TwoWay obligado. Sí, así es como está destinado. Entonces, ahora puede preguntar "¿Esto significa que el concepto de NO PERMITIR que los datos inválidos pasen al modelo es inútil en MVVM si usamos IDataErrorInfo"?
¡No en realidad!
Ver MVVM no hace cumplir una regla que SÓLO los datos válidos deben volver. Acepta datos no válidos y así es como funciona IDataErrorInfo
y aumenta la notificación de errores. El punto es ViewModel es una mera softcopy de su Vista por lo que puede ser sucio. Lo que debe asegurarse es que esta suciedad no sea comprometida en sus interfaces externas, como servicios o base de datos.
Este flujo de datos no válidos debe estar restringido por el ViewModel
al probar los datos no válidos. Y esa información vendrá si tenemos activado el enlace TwoWay
. Entonces, teniendo en cuenta que está implementando IDataErrorInfo
, entonces necesita tener enlaces TwoWay
, lo cual está perfectamente permitido en MVVM.
Enfoque 1:
¿Qué pasa si wan para validar explícitamente ciertos elementos de la interfaz de usuario de clic de botón?
Para esto, use un truco de validación demorada. En su ViewModel tiene una bandera llamada isValidating. Establecerlo como falso por defecto.
En su propiedad IDataErrorInfo.this
omitir la validación mediante la comprobación de la bandera isValidating ...
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;
}
}
A continuación, en el comando OK ejecutado controlador, compruebe el nombre del empleado y luego subir los eventos de notificación de cambio de propiedad de la misma propiedad ...
private void OnSaveNameCommandExecute(object param)
{
isValidating = true;
this.NotifyPropertyChanged("EmployeeName");
isValidating = false;
}
Esto activa la validación SÓLO al hacer clic en Aceptar. Recuerde que EmployeeName
TIENE que contener datos no válidos para que la validación funcione.
Enfoque 2:
¿Qué pasa si quiero actualizar de forma explícita fijaciones sin modo de TwoWay en MVVM?
Luego tendrá que usar Attached Behavior
. El comportamiento se adjuntará al botón Aceptar y aceptará una lista de todos los elementos que necesitan que se actualicen sus enlaces.
<Button Content="OK">
<local:SpecialBindingBehavior.DependentControls>
<MultiBinding Converter="{StaticResource ListMaker}">
<Binding ElementName="EmployeeNameTxBx" />
<Binding ElementName="EmployeeSalaryTxBx" />
....
<MultiBinding>
</local:SpecialBindingBehavior.DependentControls>
</Button>
El ListMaker
es una IMultiValueConverter
que simplemente convierte los valores en una lista ...
Convert(object[] values, ...)
{
return values.ToList();
}
En su SpecialBindingBehavior
tienen un cambio de manejador DependentControls
propiedad ...
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();
}
});
}
}
Pero aún así voy a sugerir que utilice mi anterior MVVM pura basada ** Enfoque 1.
primero gracias por su respuesta detallada! y volviendo a mi problema, estoy usando mvvm puro y tengo comando en mi vm y estoy usando NotifyPropertyChanged. pero si uso el enlace OneWay y tengo en la ventana 10 cuadros de texto significa que necesito enviar los parámetros de comando 10 nombres de elementos? y luego actualizarlos manualmente? no hay forma de usar el enlace ToWay? – Maya
también en este momento estoy usando IDataError para validar el texto en los cuadros de texto, si voy a usar el enlace OneWay ¿puedo todavía validar el texto? – Maya
@Maya, por favor, vea mi naswer editado arriba. –