我们说我有一个绑定到某些DataContext的WPF控件。现在让我们说我有一些需要从DataContext获取值的UI代码。我该怎么做?
我知道以下解决方法:
将DataContext转换为其原始类型,例如
var myValue = ((MyViewModel)myControl.DataContext).SomeProperty;
或
var myValue = ((DataRowView)myControl.DataContext).Item("SomeDatabaseField");
我不喜欢这样,因为这意味着我的UI代码中的 我需要有关基础数据源类型的信息。
将所需值绑定到某个UI字段并从那里提取,例如
<Button Click="..." Tag="{Binding SomeProperty}" />
并在代码中
var myValue = (TypeOfMyValue)myButton.Tag;
是否有一些泛型方法从DataContext中提取值,即执行Binding
做什么来获取值?我正在寻找这样的事情:
var myValue = SomeGenericExtractMethod(myControl.DataContext, "SomeProperty");
我很确定这样的东西存在(毕竟,Binding
就像这样),我找不到它......
答案 0 :(得分:1)
答案是反思。这适用于非索引属性:
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
this.DataContext = new MyViewModel();
var myValue = this.DataContext.GetType().GetProperty("MyIntValue").GetValue(this.DataContext, null);
}
}
public class MyViewModel
{
private int myIntValue = 6;
public int MyIntValue
{
get
{
return this.myIntValue;
}
}
}
答案 1 :(得分:1)
我发现了一种适用于ViewModel类(CLR属性)和绑定到ADO.NET DataTables(DataRowView字段)的列表的方法,即使用两者提供的TypeDescriptor:
var myValue = TypeDescriptor.GetProperties(myControl.DataContext)["SomeProperty"]
.GetValue(myControl.DataContext);
这是一个简短的工作示例:
var vm = new { MyString = "Test1" }; // ViewModel
var dt = new DataTable();
dt.Columns.Add("MyString", typeof(String));
dt.Rows.Add("Test2");
var drv = dt.DefaultView[0]; // DataRowView
var value1 = TypeDescriptor.GetProperties(vm)["MyString"].GetValue(vm);
var value2 = TypeDescriptor.GetProperties(drv)["MyString"].GetValue(drv);
// value1 = "Test1", value2 = "Test2"
答案 2 :(得分:-1)
您可能需要自己构建它。我们在工作中这样做了,但我无法共享代码,因为它是一个内部资产。虽然它不是太容易,但也不是太难以思考也尊重索引属性f.e ..仍然应该在一天内完成。您使用反射来获取值,但请确保缓存生成的getter。它不仅仅是那个。真的...... :)。
有些人认为这不是一个好方法,也许有关于此的更多信息: 给定复杂的属性路径,您可以循环遍历路径并逐个解析对象。创建一个获取DataContext-Instance的Resolver-Class。创建getter-delegates并为propertytype和propertypath(只是段)缓存它们。这变得非常快。 WPF唯一不同的是Value-Getter。它分析属性的类型。 INotifyPropertyChanged-Supporters和DependendyObjects的处理方式不同,但如果缓存委托,它不会造成很大的性能问题......