2009-02-02 6 views
82

WPF에서이 시나리오의 개체 메서드에 어떻게 바인딩합니까?WPF에서 메서드에 바인딩할까요?

public class RootObject 
{ 
    public string Name { get; } 

    public ObservableCollection<ChildObject> GetChildren() {...} 
} 

public class ChildObject 
{ 
    public string Name { get; } 
} 

XAML :

나는 트리의 각 RootObjectGetChildren 방법에 바인딩 할 다음
<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> 

. ObjectDataProvider 바인딩

편집은 내가 항목의 목록과 ObjectDataProvider 요구하거나 정적 메서드에 바인딩하고 있습니다 때문에 작동하지 않는 것, 또는 그것이 자신의 인스턴스의 그 사용 만듭니다. 매트의 답변을 사용하여 예를 들어

, 내가 얻을 :

System.Windows.Data Error: 33 : ObjectDataProvider cannot create object; Type='RootObject'; Error='Wrong parameters for constructor.'

System.Windows.Data Error: 34 : ObjectDataProvider: Failure trying to invoke method on type; Method='GetChildren'; Type='RootObject'; Error='The specified member cannot be invoked on target.' TargetException:'System.Reflection.TargetException: Non-static method requires a target.

+0

네 말이 맞아. ObjectDataProvider는 특정 인스턴스에서 메서드를 호출하는 ObjectInstance 속성을 가지고 있지만 종속성 속성이라고 생각하지 않으므로 바인딩 할 수 없습니다 (AFAIK). –

+1

그래, ObjectInstance에 바인딩하려고했는데 그것이 의존성 속성이 아니라는 것을 알았습니다. –

+0

나는 어쨌든 거기에 내 대답을 남겨 둘 것입니다, 당신의 업데이트 내용을 알려주고 비슷한 문제를 가진이 질문을 찾는 다른 누군가를 도울 것입니다. –

답변

22

아니 그것은 당신의 시나리오에서 작동하지만 당신이 특정 메서드를 호출하도록 ObjectDataProvider에 MethodName 속성을 사용하는 방법을 잘 확인 (특정과 매개 변수 (예 : MethodParameters 속성)를 사용하여 데이터를 검색합니다. 두 개의 매개 변수 (0 TempType.Celsius)을 통과,

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

그래서는 "TemperatureScale"클래스의 인스턴스에 "ConvertTemp"방법을 부르고 ObjectDataProvider가있다 : 여기

은 MSDN 페이지에서 직접 촬영 한 조각이다 .

+0

답변에 따라 답변을 업데이트했습니다. –

9

메서드에 바인딩해야합니까?

getter가 메소드 인 속성에 바인딩 할 수 있습니까?

public ObservableCollection<ChildObject> Children 
{ 
    get 
    { 
     return GetChildren(); 
    } 
} 
+0

메서드에 바인딩해야합니다. –

+2

카메론의 의견을 듣고 속성을 추가 할 수없는 유형에 바인딩한다는 의미입니다. –

+1

메서드가 잠재적으로 길게 실행될 수있는 경우 메서드 esp를 호출하는 속성에 바인딩하지 않아야합니다. 그러한 메소드를 가지면 코드 소비자가 속성이 로컬 변수에만 액세스 할 것으로 기대하므로 속성이 좋은 디자인이 아닙니다. – markmnl

4

당신이 메소드를 호출 할 수있는 속성을 추가 (또는 속성을 추가 래퍼 클래스 생성) 나는의 ValueConverter을 사용하고 알고있는 유일한 방법으로 할 수 있습니다하지 않는 한.

3

ObjectDataProvider 또한 동적 유형에 대한 속성을 정의 System.ComponentModel를 사용할 수있는 대신 개체 유형

3

사용할 수있는의 ObjectInstance 속성을 (그들이 컴파일 된 메타 데이터의 일부가 아닌 것)이있다. WPF에서이 접근법을 사용하여 필드에 바인딩을 사용할 수 없기 때문에 필드에 값을 저장 한 유형에 바인딩 할 수있었습니다.

ICustomTypeDescriptorTypeDescriptionProvider 유형을 사용하면 원하는 것을 얻을 수 있습니다. this article에 따르면

TypeDescriptionProvider allows you to write a separate class that implements ICustomTypeDescriptor and then to register this class as the provider of descriptions for other types.

나는이 자신을 접근 시도하지 않은,하지만 난 그것이 당신의 경우에 도움이되기를 바랍니다.

59

이 같이 사용되는 있도록 당신을 위해 작동 할 수 있습니다 것은, 매개 변수 등의 방법 이름을 사용 지정을 IValueConverter 만드는 것입니다 또 다른 방법 :

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

이 컨버터는 찾아 메소드를 호출 할 것이다 반사를 사용 하여. 이를 위해서는 메소드에 인수가 필요하지 않습니다.

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

하여 해당 단위 테스트 :이 변환기 targetType 파라미터를 적용하지 않는 것을

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

참고

은 여기 이러한 변환기의 소스의 예이다.

+4

흠, ... 해킹처럼 보이지만 이것이 유일한 길일 수도 있다고 생각하기 시작했습니다. 그것은 가장 쉽을거야. – Stimul8d

0

WPF 시나리오에서 개체의 메서드에 바인딩하려면 대리자를 반환하는 속성에 바인딩 할 수 있습니다.

관련 문제