如何处理不支持绑定的图表?

时间:2011-12-21 11:40:32

标签: c# wpf mvvm

我正在使用不支持mvvm意义上的绑定的图表工具。所以我决定使用一种消息传递(比如MVVM Light的消息传递框架)服务,这样每次更新viewmodel observablecollection时,都会发送一条消息,当收到该消息时会向数据库添加数据点(这将是在遗憾的代码中)。你们看到这个计划有什么问题吗?

2 个答案:

答案 0 :(得分:1)

我个人认为,消息传递对于你想要达到的目标来说有点过分,但味道很重要。你能不能使用适配器或附加的行为模式?这就是他们通常用来替代缺失功能的东西。如果您可以在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>

答案 1 :(得分:0)

您是否考虑过使用界面将视图注入ViewModel以保持分离?我知道这打破了MVVM,但我已成功地在许多WPF项目中使用它。我称之为 MiVVM or Model Interface-to-View ViewModel

模式很简单。您的Usercontrol应该有一个接口,称之为IView。然后在ViewModel中你有一个属性为IMyView的setter,比如说

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 Software Services支持MVVM,同时保持高性能的编程API。图表组件称为SciChart,它使用即时模式渲染和多个绘图优化来为科学/金融应用程序生成非常高性能的图表。

有一个演示项目在上面的博客链接上展示了这种模式。如果您使用第三方控件,我主张尝试MiVVM的附加属性实现。