2010-02-21 11 views
13

Tengo problemas para vincular una propiedad TextBox.Text con el método de un objeto. La idea es permitir al usuario escribir en un TextBox un nombre de archivo y luego tener un resultado TextBlock de ese archivo.Enlace de datos a un método en WPF

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

Aquí es mi XAML:

<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> 

Por alguna razón no está haciendo nada. ¿Alguno de ustedes podría señalar cuáles pueden ser las razones? Esto es lo que veo en el diseñador y cuando corro la aplicación:

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

Y aquí es lo que sucede cuando intento configurar otro texto en tiempo de ejecución:

alt text http://img684.imageshack.us/img684/1057/b52pnq1dm4i23qivizvpaqq.png Aquí está la error dado por de depurador cuando se trata de establecer otro texto en tiempo de ejecución:

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

Tienes que cambiar la idea de método de enlace a la propiedad. y aprende el concepto de INotifyPropertyChanged & DataContext. Google también un patrón MVVM. –

+4

+1 para hacer una pregunta que ayudará a muchas personas que no entienden el enlace de datos. –

Respuesta

0

Ok , parece un error cuando se ejecuta WPF 4.0, como se puede ver en los comentarios 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 …

Al compilar en 3.5, funciona bien aquí.

0

Es el conjunto DataContext? En su código subyacente, ¿configuró el valor de su TextBlock en "saadsas" (lo único que puedo adivinar), lo que rompió su enlace de datos?

+0

Edité mi publicación original. Básicamente todo lo que escribí en mis archivos de código está ahí. No configuré un DataContext. De hecho, ahora estoy buscando en Google lo que es un DataContext. –

1

La vinculación de datos requiere que se llame al evento NotifyPropertyChanged cuando se actualiza la fuente. En este caso, usted querrá para envolver esta llamada de función en un get/set de este modo:

 


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

Voy a probar este código. ¿Pero no hay una solución más simple para ejecutar solo algún método de una clase determinada dados algunos parámetros? –

+2

@devoured, si prefiere hacerlo de la manera correcta de WPF, este debería ser el código que necesita usar. No hay nada loco sucediendo en el código anterior, si aprendes esto te ayudará para siempre con WPF. en cualquier WPF basado en MVVM, puede ver este pequeño fragmento de código. Entonces vale la pena aprender. –

+0

Veo tu punto. Lo aprenderé de esta manera entonces. –

2

Parece que usted necesita para obtener una comprensión de MVVM, marque este artículo clásico http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

+0

Sí, pero como señalé en mi publicación, la idea es escribir lo que quiere en el cuadro de texto en tiempo de ejecución. Sé que está haciendo lo que debería con la cadena que le estoy dando en el momento del diseño dentro de las etiquetas . –

8

Si bien es posible utilizar Binding para llamar a un método y obtener su valor de retorno, no es sencillo. Es mucho más fácil de vincular a las propiedades, y utilizar la combinación de enlace y notificación de cambio para obtener el resultado que está buscando.

Cree una clase con dos propiedades, Filename y Extension. Filename es solo una propiedad de cadena de lectura/escritura. Extension es una propiedad de cadena de solo lectura cuyo captador llama al método al que está intentando llamar.

Ahora haga que la clase implemente INotifyPropertyChanged, porque si una propiedad puede cambiar de código, necesita una forma de decirle a la vinculación que lo ha hecho. Haga que el establecimiento de la propiedad Filename notifique los enlaces que la propiedad Extension ha cambiado.

Agregue Binding a TextBox que se une a la propiedad Filename utilizando el modo TwoWay. Agregue un Binding a un TextBox que se una a Extension utilizando el modo predeterminado OneWay.

La secuencia de eventos es:

  1. usuario escribe una nueva Filename en una cota TextBox y presiona TAB.
  2. El TextBox pierde el foco.
  3. Dado que el modo Binding es TwoWay, y está utilizando el comportamiento predeterminado de actualizar la fuente cuando el objetivo pierde el foco, eso es lo que hace.
  4. El Binding actualiza la fuente llamando al colocador Filename.
  5. El colocador Filename plantea PropertyChanged.
  6. El Binding se encarga de PropertyChanged, examina su argumento y ve que la propiedad Extension ha cambiado.
  7. El Binding llama captador de la propiedad Extension.
  8. El getter de la propiedad Extension llama al método para determinar la extensión para Filename, y la devuelve al Binding.
  9. El Binding actualiza su objetivo TextBox con el nuevo valor de Extension.

Este es el concepto central subyacente al enlace de datos y el patrón MVVM. Una vez que lo entiendes, se convierte en una segunda naturaleza, y el desarrollo de WPF se vuelve aproximadamente diez millones de veces más fácil.

+0

estoy usando Sam de aprender por su cuenta WPF en 24 horas ebook y he toneladas aprendido hasta ahora y ony im en el capítulo 6 (el capítulo de enlace de datos), con mucho, una de las maneras más fáciles de aprender WPF. Pasé horas buscando recursos en línea y este libro es, con mucho, el mejor que he encontrado para los principiantes de WPF. :) –

Cuestiones relacionadas