2010-04-01 14 views
5

¿Cómo puedo tener un cuadro de diálogo para editar las propiedades de una clase con enlace y tener OK-Cancelar en el cuadro de diálogo?Editar cuadro de diálogo, con enlaces y Aceptar/Cancelar en WPF

Mi primera idea era la siguiente:

public partial class EditServerDialog : Window { 
    private NewsServer _newsServer; 

    public EditServerDialog(NewsServer newsServer) { 
     InitializeComponent(); 

     this.DataContext = (_newsServer = newsServer).Clone(); 
    } 

    private void ButtonClick(object sender, RoutedEventArgs e) 
    { 
     switch (((Button)e.OriginalSource).Content.ToString()) { 
      case "OK": 
       _newsServer = (NewsServer)this.DataContext; 
       this.Close(); 
       break; 
      case "Cancel": 
       this.Close(); 
       break; 
     } 
    } 
} 

Cuando en el interruptor, la caja "OK", el DataContext contiene la información correcta, pero la instancia servidor de noticias aprobada originalmente no cambia.

+0

Podría ser útil si muestra la configuración de encuadernación. –

+0

Ejemplo de enlace: {Vinculación NeedAuthentication, UpdateSourceTrigger = LostFocus, Mode = TwoWay}. El enlace es correcto porque this.DataContext contiene los datos correctos. – ErikTJ

Respuesta

1

La instancia original de su objeto NewsServer no se ha modificado porque en realidad no la ha modificado. Después de su constructor se llama usted tiene los siguientes tres NewsServer referencias:

newsServer = original instance 
_newsServer = original instance 
DataContext = clone of original instance 

después el botón OK se hace clic en las referencias serán las siguientes:

newsServer = original instance 
_newsServer = clone of original instance (possibly modified) 
DataContext = clone of original instance (possibly modified) 

Recuerde que los objetos son los tipos de referencia, en su asignación a _newsServer solo está actualizando su referencia, no el valor del objeto en sí.

Para permitir la actualización del objeto NewsServer en sí, hay dos opciones que se le ocurren, es probable que existan otras opciones, la primera es probablemente la más simple.

  • implementar un método en el objeto void Update(NewsServer source)NewsServer continuación, en lugar de realizar la nueva asignación para el campo _newsServer lugar llamar al método de actualización en él y pasarle el valor DataContext referencia.
  • Exponga el valor _newsServer con una propiedad pública/interna. Puede hacer uso de esto a través de una variedad de mecanismos: responder explícitamente a un evento que se produce cuando cambia el valor de la propiedad; enlazar a la propiedad (por ejemplo, convertirla en una propiedad de dependencia o implementar INotifyPropertyChanged); o simplemente espere que la persona que llama recupere el valor si y cuando el método ShowDialog() retorna con un valor de true.

Tenga en cuenta que si devuelve un poco de la lógica a la persona que llama, su clase de diálogo puede ser más simple. En particular, un enfoque es solo mantener el objeto clonado, expuesto a la persona que llama a través de una propiedad (por ejemplo, deshacerse del campo _newsServer y simplemente usar DataContext). Este objeto estaría vinculado a los elementos del diálogo como antes. El llamador simplemente recuperaría la referencia de esta instancia en un resultado true del método ShowDialog().

Por ejemplo:

NewsServer newsServer = ...; 
EditServerDialog editServerDialog = new EditServerDialog(newsServer); 

if (editServerDialog.ShowDialog() == true) 
{ 
    newsServer = editServerDialog.DataContext; 
} 

El objeto clonado simplemente sería ignorado por la persona que llama si el cuadro de diálogo se cancela, y por lo tanto el método ShowDialog() devuelve false. Podría reutilizar la propiedad DataContext como se muestra arriba, o podría crear una propiedad diferente (por ejemplo, NewsServer) que simplemente devuelve el valor de propiedad DataContext (es decir, hacer que el código sea un poco más claro en la interfaz pública de la clase de diálogo).

+0

¿Cómo debo hacer esto y todavía puedo cancelar y/o solicitar? – ErikTJ

3

Pregunta anterior, pero la responderé para futuros lectores ...

Tiene que establecer UpdateSourceTrigger="Explicit" en sus enlaces para que no actualicen la fuente real hasta que el usuario haga clic en Aceptar. A continuación, en su controlador de botón Aceptar puede escribir:

BindingExpression be = MyTextBox.GetBindingExpression(TextBox.TextProperty); 
if (be!=null) be.UpdateSource(); 

También si desea restablecer fijaciones a sus iniciales en uso estatal

BindingExpression be = MyTextBox.GetBindingExpression(TextBox.TextProperty); 
if (be!=null) be.UpdateTarget(); 

Si el diálogo es complejo es posible que desee caminar todos sus controles de forma recursiva .

0

Esta es una vieja pregunta, pero recientemente encontré esto y encontré que hay una manera mejor de manejarlo con .NET 4.5.

En primer lugar, marcar sus fijaciones UpdateSourceTrigger tan explícita:

<CheckBox IsChecked="{Binding MyProperty, UpdateSourceTrigger=Explicit}"/> 

Luego, en el controlador de eventos de clic de botón Ok utilizar este:

foreach (var be in BindingOperations.GetSourceUpdatingBindings(this)) 
{ 
    be.UpdateSource(); 
} 

GetSourceUpdatingBindings es un nuevo método en .NET 4.5.

El botón Cancelar no necesita hacer nada, ya que los enlaces se han marcado como Explícitos y solo se "confirmarán" cuando se llame a UpdateSource.

Cuestiones relacionadas