2010-03-01 13 views
2

我有一个简单的silverlight工具包Chart和一个标准Slider在同一控制。我希望只要滑块值发生变化就更新图表。这应该很简单。我尝试绑定滑块上的.ValueChanged事件,但这似乎太频繁地触发(例如:在滑块仍在运动时多次)。我只对滑块停止时的值感兴趣。如果我更新的次数与事件被解雇一样频繁,那么表现非常糟糕。所以我添加了一些处理程序到.MouseLeftButtonUp.MouseLeftButtonDown事件,这些事件应该锁定或解锁更新图表的逻辑。不幸的是.MouseLeftButtonDown无法触发(处理程序中的断点没有被触发)。所以这条路线似乎也是一个非首发。如何冷静这个超级事件听众

我对silverlight非常陌生,所以我正在寻找建设性的批评方法以及可能的解决方案。干杯!

MainPage.xaml.cs中:

using System; 
using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Controls.DataVisualization.Charting; 
using System.Windows.Input; 

namespace ControlledModelView.Media 
{ 
    public partial class MainPage : UserControl 
    { 
     readonly Dictionary<KeyValuePair<int, int>, Dictionary<string, double>> data = new Dictionary<KeyValuePair<int, int>, Dictionary<string, double>>(); 
     readonly Chart chart = new Chart { VerticalAlignment = VerticalAlignment.Top }; 
     private static bool sliderInMotion = true; 
     public MainPage() 
     { 
      InitializeComponent(); 
      var rng = new Random(); 
      for (var i = 0; i < 4; i++) 
       for (var d = -1; d >= -31; d--) 
        data.Add(new KeyValuePair<int, int>(i, d), GetRandomData(rng)); 

      var slider = new Slider { LargeChange = 7, SmallChange = 1, Minimum = -31, Maximum = -1, Value = -1, VerticalAlignment = VerticalAlignment.Bottom }; 
      slider.ValueChanged += SliderValueChanged; 
      slider.MouseLeftButtonUp += SliderRelease; 
      slider.MouseLeftButtonDown += SliderLock; 
      DrawLineChart(-1); 
      LayoutRoot.Children.Add(chart); 
      LayoutRoot.Children.Add(slider); 
     } 

     static void SliderLock(object sender, MouseButtonEventArgs e) 
     { 
      sliderInMotion = true; 
     } 

     static void SliderRelease(object sender, MouseButtonEventArgs e) 
     { 
      sliderInMotion = false; 
     } 

     void SliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) 
     { 
      if(!sliderInMotion) 
       DrawLineChart((int)e.NewValue); 
     } 

     private void DrawLineChart(int day) 
     { 
      chart.Series.Clear(); 
      for (var seriesIndex = 0; seriesIndex < 4; seriesIndex++) 
      { 
       chart.Series.Add(new LineSeries 
       { 
        ItemsSource = data[new KeyValuePair<int, int>(seriesIndex, day)], 
        DependentValuePath = "Value", 
        IndependentValuePath = "Key", 
        AnimationSequence = AnimationSequence.Simultaneous, 
        Name = "Line" + seriesIndex, 
        Title = "Line" + seriesIndex, 
        IsSelectionEnabled = false, 
        Visibility = Visibility.Visible, 
        IsEnabled = true 
       }); 
      } 
     } 

     static Dictionary<string, double> GetRandomData(Random rng) 
     { 
      var data = new Dictionary<string, double>(); 
      for (var year = 1995; year < DateTime.Now.Year; year ++) 
       data.Add(year.ToString(), 500000 * rng.NextDouble()); 
      return data; 
     } 
    } 
} 

MainPage.xaml中:

<UserControl x:Class="ControlledModelView.Media.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"> 
    <Grid x:Name="LayoutRoot" /> 
</UserControl> 

回答

2

这似乎是对RX框架(的IObservable)一个最好的例子,如果你能使用它。 其中一个标准样本按坐标列出过滤事件(对于感兴趣区域中的MouseClick事件)。您可以使用正好作为您的示例。

有关详细信息,请参阅this question。得到它here

+0

酷,有一个现在读.... – grenade 2010-03-01 16:25:43

+0

Rx也可以扼杀事件,使他们只能发射,比如说,每150毫秒一次。这节省了我的一个项目的一天。 – 2010-03-01 16:29:03

1

手榴弹,

我不是一个Silverlight开发人员,尽管可能有更好的方法可以做到你想要什么,看起来完全可以接受的解决方案(如果它的工作)。这很清楚,很明显它试图做什么。

由于看起来不起作用,我的直接反应是看看他们是否可能会起作用的LostFocus事件,尽管这并不能让你想要的地方,因为他们必须取消选择控制。然而,这个思维过程让我想知道一个不同的控制可能会更好吗?例如一个用户可以直接键入数字的数字,大多数不会继续点击,所以你会得到更少的更新。

但是,这是采取整个“如果你不能解决问题,改变问题”路线... sorta。