最近在实现一些控件,诸如仪表盘
和长历史图表
等。这些控件对外的接口只有一个依赖属性Value
。通过绑定,可以实时接收后台产生的数据。
public Object Value
{
get { return (Object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
nameof(Value),
typeof(Object),
typeof(LongHistoryChart),
new PropertyMetadata(0, new PropertyChangedCallback(OnValuePropertyChanged)));
对于一般的控件而言,如仪表盘
,通过向 PropertyMetadata 提供更改通知的回调OnValuePropertyChanged
就可以实现仪表盘
上的指针位置的更新。
然而,对于长历史图表
而言,它还有一个额外的要求:保存历史的数据。这时,问题就出现了。如果后台产生了连续的相同的数据,那么OnValuePropertyChanged
的回调将不会被调用,进而导致长历史图只会保存连续变化的数据。这显然不是我们想要的效果。
那如何解决这个问题呢?可以在控件内部编写UpdateValue()
方法,由后台主动调用数据更新(这里更新的概念就包括了连续相同的数据)。
注:由于我的代码中控件和后台数据更新对象没有耦合在一起,所以为了能主动调用数据更新,我还用到了反射技术调用此方法,所以接下来定义的
UpdateValue()
方法甚至是私有的(private)。
UpdateValue()
方法///
/// 主动更新长历史图
///
private void UpdateValue()
{
// 依赖属性的描述符,可以用于获取属性的值、监听属性变化等
var descriptor = DependencyPropertyDescriptor.FromProperty(
ValueProperty, //提供的依赖属性
typeof(LongHistoryChart)); //目标对象类型:要为其设置依赖属性的对象的类型
// 获取依赖属性的值
var value = descriptor.GetValue(this);
// 下面是更新长历史图的逻辑,省略咯
//....
}
UpdateValue()
方法 // 通过反射调用控件的更新
// 这一句是获取控件的类型,一般可以通过控件对象通过反射,例如这里其实可以换成controlObject.GetType()
// 我这里提供的示例不是通用的代码,是开源代码库daimicsharpcode/WpfDesigner中的类
Type controlType = node.FirstProperty.DesignItem.ComponentType;
// 这一句是获取控件对象
var controlObject = node.FirstProperty.DesignItem.Component;
if (controlType != null)
{
// 设置反射搜索范围:私有的非静态的方法
BindingFlags flag = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod;
// 搜索指定搜索范围的名称为"UpdateValue"的方法
MethodInfo method = controlType.GetMethod("UpdateValue",flag);
if (method != null)//调用前判断是否存在这个方法
{
// 反射调用方法
method.Invoke(controlObject, flag, Type.DefaultBinder, null, null);
}
}
本文仅仅简单介绍了WPF 通过依赖属性Value更新长历史图表
,如果对你有帮助,请点个赞,如有纰漏或者你有更好的方法,烦请留言,不吝赐教,感激不尽。