Enlace WPF al miembro de la clase en el código detrás


Pregunta bastante simple, pero parece que no puede encontrar una respuesta completa aquí...

Necesito databind en xaml a una propiedad de un miembro de la clase en codebehind.

<Window x:Class="Main">
    <customcontrol Name="View" IsChecked="{Binding ElementName=RecordProp, Path=IsViewChecked}" />
...

Donde el código detrás se ve como:

class Main 
{    
    ...
    private Record _record;
    public Record RecordProp
    {
      get { return _record; }
    }
    ...
}


class Record
{
  public bool IsViewChecked
  {
    get; set;
  }
}

Lo que tengo ahora no funciona, ¿qué estoy haciendo mal?

Author: jaws, 2010-03-03

4 answers

Path necesita una fuente para ir contra (Source, DataContext, RelativeSource, ElementName). ElementName solo se puede usar para referirse a elementos declarados en XAML por su nombre x:. Pruebe esto en su lugar para apuntar a su ventana como la fuente:

IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=RecordProp.IsViewChecked}"
 26
Author: John Bowen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-02 21:49:36

Lo que estoy viendo aquí es que el nombre de clase de su ventana es Main, que ha agregado una propiedad RecordProp a ella, y que ahora está tratando de vincularse a la propiedad IsChecked del elemento llamado RecordProp. Creo que estás un poco confundido sobre cómo funcionan los nombres.

Agregar el atributo x:Name a un elemento XAML crea un campo en la clase window con ese nombre. Esto le permite hacer referencia a elementos nombrados en su código, y probablemente le ha llevado a pensar que el enlace puede hacer lo mismo cosa.

Pero así no es como el enlace encuentra elementos con nombre. El atributo x:Name también toma el objeto que el elemento XAML crea y lo registra bajo ese nombre en el namescope de la ventana. (Véase El artículo de MSDN sobre los namescopes XAML.) Eso es lo que busca el enlace para resolver los nombres de los elementos. Dado que nunca está agregando el objeto al namescope, establecer la propiedad ElementName en un enlace no lo encontrará.

Hay un par de cosas que podría posiblemente sí. Si realmente desea enlazar a una propiedad de la ventana, puede darle un nombre a la ventana y enlazar a la propiedad usando una ruta de propiedad:

<Window x:Name="MainWindow" x:Class="Main">
...
   <customcontrol Name="View" IsChecked="
                 {Binding ElementName=MainWindow, 
                  Path=RecordProp.IsViewChecked}" />

Aún más simple es simplemente establecer el contexto de datos en el constructor:

DataContext = this;

Una vez que lo hagas, puedes enlazar a la propiedad RecordProp (y cualquier otra propiedad de la ventana) de la siguiente manera:

<customControl Name="View" IsChecked={Binding RecordProp.IsChecked}/>

Por supuesto, eso no funcionará si necesita que el contexto de datos de la ventana se establezca en algo else.

Otra posibilidad es implementar la propiedad de esta manera:

public Record RecordProp 
{
  get { return (Record)Resources["RecordProp"]; }
  set { Resources["RecordProp"] = value; }
}

Puede enlazar a esto usando (por ejemplo) Binding {DynamicResource RecordProp}, Path=IsChecked". Dado que es un recurso dinámico, si algo externo a la ventana establece la propiedad RecordProp de la ventana, los enlaces a ella se actualizarán, lo cual es algo que no sucederá si solo crea RecordProp una propiedad (a menos que implemente una notificación de cambio).

 29
Author: Robert Rossney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-03 00:07:55

Creo que tengo una respuesta más simple que las indicadas hasta ahora. Simplemente agregue esto a la declaración de la ventana (la primera etiqueta) en XAML:

x:Name="this"

Entonces puedes databind así:

<customcontrol Name="View" IsChecked="{Binding ElementName=this, Path=RecordProp.IsViewChecked}" />

Revisé para ver si C# se queja de que ya hay un "esto", y no lo hizo, supongo que porque ambos se refieren exactamente al mismo objeto.

Esta es la solución que usé cuando me encontré con el mismo problema, y me pareció muy intuitivo de usar.

 6
Author: JoeCool,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-18 16:41:49

El enlace de datos no funcionará con campos privados. Está destinado a propiedades públicas en su lugar. Intente exponer el valor _record públicamente y enlazar a eso en su lugar.

Referencia - http://msdn.microsoft.com/en-us/library/ms743643.aspx

 3
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-02 21:34:29