92 votes

Lier à une méthode dans WPF ?

Comment voulez-vous lier à un des objets de cette méthode dans ce scénario dans 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>

Ici, je veux lier à l' GetChildren méthode sur chaque RootObject de l'arbre.

MODIFIER la Liaison à un ObjectDataProvider semble ne pas fonctionner, parce que je suis de liaison à une liste d'éléments, et l' ObjectDataProvider des besoins, soit une méthode statique, ou il crée sa propre instance et l'utilise.

Par exemple, à l'aide de Matt réponse que j'obtiens:

Système.De Windows.Erreur de données: 33 : ObjectDataProvider ne peut pas créer d'objet; Type='RootObject'; Erreur='Mauvais paramètres pour le constructeur.'

Système.De Windows.Erreur de données: 34 : ObjectDataProvider: Échec en essayant d'appeler la méthode type; Method='GetChildren'; Type= "RootObject'; Erreur='Le membre spécifié ne peut pas être invoquée sur la cible.' TargetException:'Système.De la réflexion.TargetException: Non méthode statique nécessite une cible.

73voto

Drew Noakes Points 69288

Une autre approche qui pourrait fonctionner pour vous est de créer un personnalisé, IValueConverter qui prend un nom de méthode en tant que paramètre, afin qu'il puisse être utilisé comme ceci:

ItemsSource="{Binding 
    Converter={StaticResource MethodToValueConverter},
    ConverterParameter='GetChildren'}"

Ce convertisseur peut trouver et d'appeler la méthode à l'aide de la réflexion. Cela exige la méthode pour ne pas avoir des arguments.

Voici un exemple d'un tel convertisseur de source:

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.");
    }
}

Et un correspondant de l'unité de test:

[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));
}

Noter que ce convertisseur de ne pas appliquer l' targetType paramètre.

26voto

Matt Hamilton Points 98268

Pas sûr de savoir comment il va travailler dans votre scénario, mais vous pouvez utiliser le MethodName bien sur ObjectDataProvider de l'avoir appeler une méthode spécifique (avec des paramètres spécifiques si vous MethodParameters propriété) pour récupérer ses données.

Voici un extrait de prises directement à partir de la page 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>

Donc, c'est un ObjectDataProvider qui appelle un "ConvertTemp" la méthode sur une instance d'un "TemperatureScale" de la classe, en passant par deux paramètres (0 et TempType.Celsius).

13voto

Michael Prewecki Points 1055

Vous avez lier à la méthode ?

Vous pouvez créer une liaison à une propriété qui a getter est la méthode ?

6voto

Nir Points 18250

À moins que vous pouvez ajouter une propriété pour appeler la méthode (ou créer une classe wrapper qui ajoute cette propriété) la seule façon que je connais utilise un ValueConverter.

3voto

Graham Ambrose Points 586

ObjectDataProvider possède également une propriété ObjectInstance qui peut être utilisée au lieu de ObjectType

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X