.net - imagenes - en html, el atributo alt se emplea para
Enlace a un método en WPF? (7)
¿Cómo se vincula a un método de objetos en este escenario en WPF?
public class RootObject
{
public string Name { get; }
public ObservableCollection<ChildObject> GetChildren() {...}
}
public class ChildObject
{
public string Name { get; }
}
XAML:
<TreeView ItemsSource="some list of RootObjects">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type data:RootObject}"
ItemsSource="???">
<TextBlock Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type data:ChildObject}">
<TextBlock Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Aquí quiero enlazar al método GetChildren
en cada RootObject
del árbol.
EDITAR La vinculación a un ObjectDataProvider
no parece funcionar porque estoy vinculando a una lista de elementos, y ObjectDataProvider
necesita un método estático o crea su propia instancia y la usa.
Por ejemplo, usando la respuesta de Matt, obtengo:
System.Windows.Data Error: 33: ObjectDataProvider no puede crear objetos; Tipo = ''RootObject''; Error = ''Parámetros incorrectos para el constructor''
System.Windows.Data Error: 34: ObjectDataProvider: Error al intentar invocar el método en el tipo; Método = ''GetChildren''; Tipo = ''RootObject''; Error = ''El miembro especificado no puede invocarse en el destino.'' TargetException: ''System.Reflection.TargetException: método no estático requiere un objetivo.
¿Tienes que unirte al método?
¿Puede vincularse a una propiedad que es getter es el método?
public ObservableCollection<ChildObject> Children
{
get
{
return GetChildren();
}
}
A menos que pueda agregar una propiedad para llamar al método (o crear una clase contenedora que agregue esa propiedad) la única forma que conozco es usar un ValueConverter.
No estoy seguro de qué tan bien funcionará en su escenario, pero puede usar la propiedad MethodName en ObjectDataProvider para que llame a un método específico (con parámetros específicos si tiene la propiedad MethodParameters) para recuperar sus datos.
Aquí hay un fragmento tomado directamente de la página de MSDN:
<Window.Resources>
<ObjectDataProvider ObjectType="{x:Type local:TemperatureScale}"
MethodName="ConvertTemp" x:Key="convertTemp">
<ObjectDataProvider.MethodParameters>
<system:Double>0</system:Double>
<local:TempType>Celsius</local:TempType>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
Entonces ese es un ObjectDataProvider que está llamando a un método "ConvertTemp" en una instancia de una clase "TemperatureScale", pasando dos parámetros (0 y TempType.Celsius
).
ObjectDataProvider también tiene una propiedad ObjectInstance que se puede usar en lugar de Object Type
Otro enfoque que podría funcionar para usted es crear un IValueConverter
personalizado que tome un nombre de método como parámetro, para que se use así:
ItemsSource="{Binding
Converter={StaticResource MethodToValueConverter},
ConverterParameter=''GetChildren''}"
Este convertidor encontraría e invocaría el método utilizando la reflexión. Esto requiere que el método no tenga ningún argumento.
Aquí hay un ejemplo de la fuente de un convertidor de este tipo:
public sealed class MethodToValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var methodName = parameter as string;
if (value==null || methodName==null)
return value;
var methodInfo = value.GetType().GetMethod(methodName, new Type[0]);
if (methodInfo==null)
return value;
return methodInfo.Invoke(value, new object[0]);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException("MethodToValueConverter can only be used for one way conversion.");
}
}
Y una prueba de unidad correspondiente:
[Test]
public void Convert()
{
var converter = new MethodToValueConverter();
Assert.AreEqual("1234", converter.Convert(1234, typeof(string), "ToString", null));
Assert.AreEqual("ABCD", converter.Convert(" ABCD ", typeof(string), "Trim", null));
Assert.IsNull(converter.Convert(null, typeof(string), "ToString", null));
Assert.AreEqual("Pineapple", converter.Convert("Pineapple", typeof(string), "InvalidMethodName", null));
}
Tenga en cuenta que este convertidor no aplica el parámetro targetType
.
Para enlazar al método de un objeto en su escenario de WPF, puede enlazar a una propiedad que devuelve un delegado.
Puede usar System.ComponentModel
para definir propiedades para un tipo dinámicamente (no son parte de los metadatos compilados). Utilicé este enfoque en WPF para habilitar el enlace a un tipo que almacenó sus valores en los campos, ya que no es posible vincularlos a los campos.
Los tipos ICustomTypeDescriptor
y TypeDescriptionProvider
pueden permitirle lograr lo que desea. De acuerdo con este artículo :
TypeDescriptionProvider
permite escribir una clase separada que implementeICustomTypeDescriptor
y luego registrar esta clase como el proveedor de descripciones para otros tipos.
No he intentado este enfoque yo mismo, pero espero que sea útil en su caso.