WPF에서 메서드에 바인딩하시겠습니까?
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>
여기서 나는 다음에 바인딩합니다.GetChildren각각의 방법RootObject나무의
에 대한 바인딩 편집ObjectDataProvider제가 아이템 목록에 바인딩되어 있기 때문에 작동하지 않는 것 같고, 그리고.ObjectDataProvider정적 메서드가 필요하거나 고유한 인스턴스를 생성하여 사용합니다.
예를 들어 Matt의 답변을 사용하면 다음과 같이 얻을 수 있습니다.
시스템. 윈도우.데이터 오류: 33 : ObjectDataProvider가 개체를 만들 수 없습니다.유형='RootObject'; 오류='생성자에 대한 매개 변수가 잘못되었습니다.'
시스템. 윈도우.데이터 오류: 34 : ObjectDataProvider:메서드='GetChildren', 유형='RootObject', 오류=' 유형에서 메서드를 호출하지 못했습니다.지정한 구성원을 대상에서 호출할 수 없습니다.'대상 예외: '시스템.반사.대상 예외: 정적 메서드가 아닌 메서드에는 대상이 필요합니다.
메서드 이름을 매개 변수로 사용하는 사용자 정의를 생성하여 다음과 같이 사용할 수도 있습니다.
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.");
}
}
해당 장치 테스트:
[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));
}
이 변환기는 다음을 수행하지 않습니다.targetType매개 변수
시나리오에서 얼마나 잘 작동할지 확실하지 않지만 속성을 사용할 수 있습니다.ObjectDataProvider특정 메소드(사용자의 특정 매개 변수 포함)를 호출합니다.MethodParameters데이터를 검색합니다.
다음은 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>
그래서 그것은ObjectDataProvider그것은 a야.ConvertTemp의 예에 의한 방법.TemperatureScale클래스, 두 매개 변수 전달(0그리고.TempType.Celsius).
당신은 그 방법을 고수해야 합니까?
당신은 그 방법이 더 나은 부동산에 묶을 수 있습니까?
public ObservableCollection<ChildObject> Children
{
get
{
return GetChildren();
}
}
메서드를 호출할 속성을 추가할 수 있는 경우(또는 해당 속성을 추가하는 래퍼 클래스를 만들 수 있는 경우)를 제외하고 내가 아는 유일한 방법은 ValueConverter를 사용하는 것입니다.
ObjectDataProvider에는 ObjectType 대신 사용할 수 있는 ObjectInstance 속성도 있습니다.
사용할 수 있습니다.System.ComponentModel컴파일된 메타데이터의 일부가 아닌 유형의 속성을 동적으로 정의합니다.필드에 바인딩할 수 없기 때문에 필드에 값을 저장한 유형에 바인딩할 수 있도록 WPF에서 이 접근 방식을 사용했습니다.
및 유형을 사용하면 원하는 것을 달성할 수 있습니다.이 기사에 따르면:
TypeDescriptionProvider를구는별클작수있성다습니할를래스를 할 수 있습니다.ICustomTypeDescriptor그런 다음 이 클래스를 다른 형식에 대한 설명 제공자로 등록합니다.
제가 직접 이런 방법을 시도해 본 적은 없지만, 당신의 경우 도움이 되길 바랍니다.
WPF 시나리오에서 개체의 메서드에 바인딩하려면 대리자를 반환하는 속성에 바인딩할 수 있습니다.
드류 노익스의 대답과 동일하지만 확장 방법을 사용할 수 있습니다.
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, Type.EmptyTypes);
if (methodInfo == null)
{
methodInfo = GetExtensionMethod(value.GetType(), methodName);
if (methodInfo == null) return value;
return methodInfo.Invoke(null, new[] { value });
}
return methodInfo.Invoke(value, Array.Empty<object>());
}
static MethodInfo? GetExtensionMethod(Type extendedType, string methodName)
{
var method = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(type => !type.IsGenericType && !type.IsNested)
.SelectMany(type => type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), (_, method) => method)
.Where(m => m.IsDefined(typeof(ExtensionAttribute), false))
.Where(m => m.GetParameters()[0].ParameterType == extendedType)
.FirstOrDefault(m => m.Name == methodName);
return method;
}
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotSupportedException("MethodToValueConverter can only be used for one way conversion.");
}
}
언급URL : https://stackoverflow.com/questions/502250/bind-to-a-method-in-wpf
'programing' 카테고리의 다른 글
| Python3에서 인덱스별로 dict_keys 요소 액세스 (0) | 2023.05.07 |
|---|---|
| 문 인쇄를 사용하여 VARCHAR(MAX)를 인쇄하는 방법은 무엇입니까? (0) | 2023.05.07 |
| 프로세스가 끝날 때까지 대기 (0) | 2023.05.07 |
| c# Excel interop 학습 리소스 (0) | 2023.05.07 |
| mongodb의 장점이 스키마가 없다는 것인데 mongoose는 왜 스키마를 사용합니까? (0) | 2023.05.07 |