Bagaimana Anda mengikat metode objek dalam skenario ini di 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>
Di sini saya ingin mengikat GetChildren
metode pada masing RootObject
- masing pohon.
EDIT Binding ke an ObjectDataProvider
tampaknya tidak berfungsi karena saya mengikat daftar item, dan ObjectDataProvider
memerlukan metode statis, atau membuat instance sendiri dan menggunakannya.
Misalnya, menggunakan jawaban Matt saya mendapatkan:
Kesalahan System.Windows.Data: 33: ObjectDataProvider tidak dapat membuat objek; Ketik = 'RootObject'; Kesalahan = 'Parameter salah untuk konstruktor.'
Kesalahan System.Windows.Data: 34: ObjectDataProvider: Kegagalan mencoba memanggil metode pada tipe; Metode = 'GetChildren'; Ketik = 'RootObject'; Error = 'Anggota yang ditentukan tidak dapat dipanggil pada target.' TargetException: 'System.Reflection.TargetException: Metode non-statis memerlukan target.
sumber
Jawaban:
Pendekatan lain yang mungkin berhasil untuk Anda adalah membuat kustom
IValueConverter
yang menggunakan nama metode sebagai parameter, sehingga akan digunakan seperti ini:Konverter ini akan mencari dan memanggil metode menggunakan refleksi. Ini membutuhkan metode untuk tidak memiliki argumen apa pun.
Berikut adalah contoh sumber konverter tersebut:
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."); } }
Dan tes unit yang sesuai:
[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)); }
Perhatikan bahwa konverter ini tidak memberlakukan
targetType
parameter.sumber
Tidak yakin seberapa baik ini akan bekerja dalam skenario Anda, tetapi Anda dapat menggunakan
MethodName
properti onObjectDataProvider
untuk memanggil metode tertentu (dengan parameter tertentu dariMethodParameters
properti Anda ) untuk mengambil datanya.Berikut cuplikan yang diambil langsung dari halaman 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>
Jadi itulah
ObjectDataProvider
yang memanggilConvertTemp
metode pada instanceTemperatureScale
kelas, meneruskan dua parameter (0
danTempType.Celsius
).sumber
Apakah Anda harus terikat pada metode ini?
Bisakah Anda mengikat ke properti yang getter adalah metodenya?
public ObservableCollection<ChildObject> Children { get { return GetChildren(); } }
sumber
Kecuali Anda dapat menambahkan properti untuk memanggil metode (atau membuat kelas pembungkus yang menambahkan properti itu) satu-satunya cara yang saya tahu adalah menggunakan ValueConverter.
sumber
ObjectDataProvider juga memiliki properti ObjectInstance yang bisa digunakan sebagai pengganti ObjectType
sumber
Anda dapat menggunakan
System.ComponentModel
untuk mendefinisikan properti untuk suatu tipe secara dinamis (mereka bukan bagian dari metadata yang dikompilasi). Saya menggunakan pendekatan ini di WPF untuk mengaktifkan pengikatan ke jenis yang menyimpan nilainya di bidang, karena pengikatan ke bidang tidak dimungkinkan.Jenis
ICustomTypeDescriptor
danTypeDescriptionProvider
memungkinkan Anda mencapai apa yang Anda inginkan. Menurut artikel ini :Saya sendiri belum mencoba pendekatan ini, tetapi saya harap ini membantu dalam kasus Anda.
sumber
Untuk mengikat ke metode objek dalam skenario WPF, Anda dapat mengikat ke properti yang mengembalikan delegasi.
sumber