Hoy en día, yo estaba trabajando en un WPF control de usuario para visualizar el valor actual de una serie de variables. Me preguntaba si habría una manera de hacer una super simple con la cuadrícula de propiedades en WPF. El problema está en la protagonizó la línea de la XAML a continuación. ¿Cómo puedo enlazar una cadena a una propiedad con un ItemTemplate como tengo el programa de instalación a continuación? Para ser más claro puedo insertar enlaces en el interior de uno a otro {Binding Path={Binding Value}}.

Aquí es el de la clase:

public class Food
{
    public string Apple { get; set; }
    public string Orange { get; set; }
    public IEnumerable<KeyValuePair<string, string>> Fields
    {
        get
        {
            yield return new KeyValuePair<string, string>("Apple Label", "Apple");
            yield return new KeyValuePair<string, string>("Orange Label", "Orange");
        }
    }
}

Y aquí está el código XAML:

<UserControl x:Class="MAAD.Plugins.FRACTIL.Simulation.SimulationStateView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="331" Width="553">
 <ListView ItemSource="{Binding Fields}">
  <ListView.ItemTemplate>
   <DataTemplate>
    <StackPanel Orientation="Horizontal">
     <TextBlock Text="{Binding Key}" />
     **<TextBlock Text="{Binding Path={Binding Value}}" />**
    </StackPanel>
   </DataTemplate>
  </ListView.ItemTemplate>
 </ListView>
</UserControl>
InformationsquelleAutor Jake Pearson | 2009-11-02

2 Comentarios

  1. 5

    La esencia del problema es que se necesita no sólo la lista de descripciones de campo y nombres, pero el objeto real que tiene los campos y nombres.

    Puede utilizar un convertidor como el que añade destino referencias a los objetos de campo y proporciona un valor de descriptor de acceso, como este:

      public class PropertyValueAccessConverter : IMultiValueConverter
      {
        object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
          var target = values[0];
          var fieldList = values[1] as IEnumerable<KeyValuePair<string,string>>;
          return
            from pair in fieldList
            select new PropertyAccessor
            {
              Name = pair.Name,
              Target = target,
              Value = target.GetType().GetProperty(target.Value),
            };
        }
    
        object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
          throw new InvalidOperationException();
        }
    
        public class PropertyAccessor
        {
          public string Name
          public object Target;
          public PropertyInfo Property;
    
          public object Value
          {
            get { return Property.GetValue(Target, null); }
            set { Property.SetValue(Target, value, null); }
          }
        }
    
        public static PropertyValueAccessConverter Instance = new PropertyValueAccessConverter();
      }

    Con este convertidor, usted puede enlazar su ItemsSource como este:

      <ListView>
        <ListView.ItemsSource>
          <MultiBinding Converter="{x:Static local:PropertyValueAccessConverter.Instance}">
            <Binding />
            <Binding Path="Fields" />
          </MultiBinding>
        </ListView.ItemsSource>
      </ListView>

    Por el camino, de una manera mucho más eficiente para implementar los Campos de la propiedad es:

      public IEnumerable<KeyValuePair<string, string>> Fields
      {
        get
        {
          return new KeyValuePair<string, string>[]
          {
            new KeyValuePair<string, string>("Apple Label", "Apple");
            new KeyValuePair<string, string>("Orange Label", "Orange");
          }
        }
      }

    Aunque, francamente, me haría uso de la descripción de los atributos de las propiedades individuales junto con la reflexión en lugar de codificar la lista. Que eliminaría la necesidad de la MultiBinding en el primer lugar.

  2. 1

    Bien, sólo debe ser:

    <TextBlock Text="{Binding Path=Value}" />

    Sin embargo, creo que entiendo lo que estás tratando de hacer. El problema es KeyValuePair no es una INotifyPropertyChange subtipo (con razón, no entrar en eso), así que nunca reciben una notificación de que si se cambia el valor en el diccionario. También, KeyValuePair es en realidad una estructura. Así, cambiando el valor en el límite de la copia no actualizar el origen de datos real porque es una copia de los datos.

    Si el Modelo que usted está trabajando con la realidad es KeyValuePair, usted necesita para crear una forma más específica de la Vista-Modelo de clase para habilitar esta databinding escenario. Esto tendría que ser algún tipo de clase que envuelve la Clave y tiene una referencia a la fuente subyacente (probablemente un Diccionario?) y en realidad hace que las llamadas a actualizar el valor en la fuente subyacente cuando su propiedad está cambiado. Dicho esto, todavía no llegan las notificaciones de un Diccionario (de nuevo, suponiendo que el origen) porque no despedir a todos, por lo que no será capaz de proporcionar adelante las notificaciones de cambio.

    • Gracias por el post, pero no estoy mirando para enlazar con Valor, pero a la propiedad con el nombre que Valor tiene. En el ejemplo anterior, uno de los pares se unen a el valor de la Naranja de la propiedad y el otro a la Manzana de la propiedad.
    • Ahhhhhhhhhhhh, yo veo lo que estás diciendo. Sí, eso simplemente no es posible. Déjame pensar y revisar mi respuesta.

Dejar respuesta

Please enter your comment!
Please enter your name here