如何处理不支持绑定的图表
本文关键字:绑定 不支持 何处理 处理 | 更新日期: 2023-09-27 18:18:34
我正在使用一个图表工具,它不支持mvvm意义上的绑定。因此,我决定使用一种消息传递(如MVVM Light的消息传递框架)服务,以便每次视图模型observablecollection被更新时,都会发送一条消息,当接收到该消息时将数据点添加到图表中(不幸的是,这将在代码后面)。你们觉得这个计划有什么问题吗?
我个人认为,对于你想要达到的目标来说,消息传递有点太过了。您可以不使用适配器或附加的行为模式吗?这就是他们通常用来替代缺失功能的方法。如果你可以在Xaml中实例化你的图表(我希望你这样做),我建议使用附加行为,否则使用和apater(对于没有公共构造函数或任何其他棘手的东西的元素)并在代码中实例化它。
对于任何只支持命令式调用的类,你总能想出一个补偿行为。下面是一个简短的示例:
代码:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public Dictionary<int, int> MyValues
{
get
{
return Enumerable.Range(1, 3).ToDictionary(k => k, v => v);
}
}
}
// component with the 'missing' property
public class Imperative : FrameworkElement
{
public void Add(int x, int y)
{
MessageBox.Show(string.Format("{0}_{1}", x, y));
}
}
// compensating behavior
public class DeclarativeBehavior : DependencyObject
{
public static DependencyProperty MissingPropertyProperty =
DependencyProperty.RegisterAttached("MissingProperty",
typeof(Dictionary<int, int>),
typeof(DeclarativeBehavior),
new PropertyMetadata((o, e) =>
{
//
Imperative imperative = (Imperative)o;
Dictionary<int, int> values = (Dictionary<int, int>)e.NewValue;
if (imperative != null)
{
foreach (KeyValuePair<int, int> value in values)
{
imperative.Add(value.Key, value.Value);
}
}
}));
public static void SetMissingProperty(DependencyObject o, Dictionary<int, int> e)
{
o.SetValue(DeclarativeBehavior.MissingPropertyProperty, e);
}
public static Dictionary<int, int> GetMissingProperty(DependencyObject o)
{
return (Dictionary<int, int>)o.GetValue(DeclarativeBehavior.MissingPropertyProperty);
}
}
}
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<!--black box, which supports imperative calls is extended to support declarative calls too-->
<local:Imperative local:DeclarativeBehavior.MissingProperty="{Binding MyValues,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Grid>
</Window>
您是否考虑过使用接口将视图注入ViewModel以保持分离?我知道这会破坏MVVM,但我已经成功地在一些WPF项目中使用了它。我称之为MiVVM或模型接口到视图视图模型。
模式很简单。你的Usercontrol应该有一个接口,叫它IView。然后在ViewModel中你有一个属性它的setter类型是IMyView,比如
public IMyView InjectedView { set { _injectedView = value; } }
然后在视图中创建一个依赖属性This
public MyUserControl : IMyView
{
public static readonly DependencyProperty ThisProperty =
DependencyProperty.Register("This", typeof(IMyView), typeof(MyUserControl));
public MyUserControl()
{
SetValue(ThisProperty, this);
}
public IMyView This { get { return GetValue(ThisProperty); } set { /* do nothing */ } }
}
最后,在Xaml中,你可以使用绑定
将视图直接注入ViewModel中。<MyUserControl This="{Binding InjectedView, Mode=OneWayToSource}"/>
试试吧!我已经使用这个模式很多次了,你会在启动时获得一个注入视图的接口。这意味着你保持了分离(Viewmodel可以被测试,IView可以被模拟),但是你绕过了许多第三方控件缺乏绑定支持的问题。另外,它很快。你知道绑定使用反射吗?
最后,我在ABT软件服务公司实现了一个图表控件,它使用这个模式来支持MVVM,同时保持一个高性能的可编程API。图表组件称为scicchart,它使用即时模式渲染和多种绘图优化来为科学/金融应用程序生成非常高性能的图表。
在上面的博客链接中有一个演示项目展示了这个模式。如果你正在使用第三方控件,我建议尝试一下MiVVM的附加属性实现。