2009-04-07 18 views
5

Parece que me encontré con un bloqueo de carretera. Estamos usando MVVM con Prism y tenemos una vista que requiere un lienzo de tinta. He creado un StrokeCollection que está vinculado desde mi ViewModel a la Vista. Puedo configurar la colección desde mi modelo de vista, pero los cambios no aparecen en ViewModel mientras el usuario dibuja. ¿Hay alguna manera de hacer que esto funcione?MVVM Encuadernación a InkCanvas

Mi Propiedad en mi modelo de vista es el siguiente:

private StrokeCollection _strokes; 
public StrokeCollection Signature 
{ 
    get 
    { 
     return _strokes; 
    } 
    set 
    { 
     _strokes = value; 
     OnPropertyChanged("Signature"); 
    } 
} 

Aquí es mi XAML línea de unión:

<InkCanvas x:Name="MyCanvas" Strokes="{Binding Signature, Mode=TwoWay}" /> 

Por alguna razón, al parecer, los InkCanvas nunca se notifica al modelo de vista de cualquier cambio.

Respuesta

11

El problema con su enfoque es que supone que el InkCanvas crea el StrokeCollection. No lo hace, simplemente agrega y elimina elementos de él. Y si la colección no está disponible (es decir, es null), el enlace fallará y el InkCanvas no hará nada con él. Por lo tanto:

  1. Es necesario crear un único StrokeCollection
  2. Es necesario asumir el contenido de la colección va a cambiar, no la propia colección

código Ejemplo:

public class ViewModel : INotifyPropertyChanged 
{ 
    private readonly StrokeCollection _strokes; 

    public ViewModel() 
    { 
     _strokes = new StrokeCollection(); 
     (_strokes as INotifyCollectionChanged).CollectionChanged += delegate 
     { 
      //the strokes have changed 
     }; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public StrokeCollection Signature 
    { 
     get 
     { 
      return _strokes; 
     } 
    } 

    private void OnPropertyChanged(string propertyName) 
    { 
     var handler = PropertyChanged; 

     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

Y XAML:

<InkCanvas Strokes="{Binding Signature}"/> 
+0

Me faltaba la sección INotifyCollectionChanged. Tenía todo lo demás, incluida la creación de instancias de StrokeCollection. Gracias Kent. – cjibo

+0

Esto funciona muy bien. Me parece interesante que InkCanvas aún se dibuje cuando _stokes es nulo incluso cuando está enlazado. – CRice

2

La clase StrokeCollection tiene un evento llamado "StrokesChanged" que siempre se dispara cuando dibuja algo en la Vista. Ese evento contiene la colección de trazos actualizados.

XAML:

<Grid> 
    <InkCanvas Strokes="{Binding Signature}"/> 
</Grid> 

VM:

public class TestViewModel : INotifyPropertyChanged 
{ 
    public StrokeCollection Signature { get; set; } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public TestViewModel() 
    { 
     Signature = new StrokeCollection(); 
     Signature.StrokesChanged += Signature_StrokesChanged; 
    } 

    void Signature_StrokesChanged(object sender, StrokeCollectionChangedEventArgs e) 
    { 
     //PUT A BREAKPOINT HERE AND CHECK 
     Signature = (System.Windows.Ink.StrokeCollection)sender; 
    } 

} 

espero que ayude!