2010-10-18 89 views
1

我有一个绑定到文本块的依赖项属性。根据依赖项属性,如果值更改,它将反映文本块中的值。资产中的数据来自实时设备。现在,只要有数据传入,它就会传播到依赖项属性,并将到达文本块。但现在我有问题,客户想要如果相同的值来了5次,然后改变文本框的背景颜色。依赖项属性的问题

但我无法收到更改通知。此时,我们很难改变设计。

你们可以请我建议我一些解决方法,并通过依赖项属性接收所有通知的价值是相同或不同的方式吗?

+0

您可以分享您所说的绑定的代码吗? – Ragepotato 2010-10-18 21:47:59

回答

0

我不确定你要做什么,但它听起来像你想跟踪来自feed的实时值是“新鲜”还是“陈旧”。如果是这样,INotifyPropertyChanged(依赖属性背后的力量)可能不会让你开心,因为它将完全依赖于该接口的实现,以确定在SAMPLE ISKEN与什么时候被告知是否会告诉你什么时候SAMPLE已经改变(它们不是相同的概念)。

根据您的控制力此,我建议你实现你的ViewModel里面的“陈旧”追踪(您使用的MVVM,对吧?)

喜欢的东西:

Model.cs :

using System; 
using System.Windows.Threading; 

namespace WpfApplication1 
{ 
    public class Model 
    { 
    private readonly double[] _data = new[] { 2.3, 2.4, 2.5, 2.4, 2.1, 2.1, 2.1, 2.1, 2.0, 2.1, 2.0, 2.1, 2.2, 2.2, 2.2, 2.2, 2.2, 2.4 }; 
    private readonly DispatcherTimer _timer = new DispatcherTimer(); 
    private int _nextSample; 


    public Model() 
    { 
     _timer.Interval = new TimeSpan(0, 0, 0, 1); 
     _timer.Tick += _timer_Tick; 
     _timer.Start(); 
    } 

    public event EventHandler<SampleTakenEventArgs> SampleTaken; 

    private void _timer_Tick(object sender, EventArgs e) 
    { 
     if (SampleTaken != null) 
     { 
     SampleTaken(this, new SampleTakenEventArgs { SampleValue = _data[_nextSample] }); 
     } 
     _nextSample = (++_nextSample%_data.Length); 
    } 
    } 
} 

View.xaml:

<Window x:Class="WpfApplication1.View" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <StackPanel> 
     <TextBlock Text="{Binding Sample}"/> 
     <TextBlock Text="{Binding StaleCount}"/> 
    </StackPanel> 
</Window> 

View.xaml.cs:

using System.Windows; 

namespace WpfApplication1 
{ 
    public partial class View : Window 
    { 
    public View() 
    { 
     InitializeComponent(); 
     DataContext = new ViewModel(); 
    } 
    } 
} 

ViewModel.cs:

using System.ComponentModel; 

namespace WpfApplication1 
{ 
    public class ViewModel : INotifyPropertyChanged 
    { 
    private readonly Model _model; 
    private double _sample; 
    private int _staleCount; 

    public ViewModel() 
    { 
     _model = new Model(); 
     _model.SampleTaken += _model_SampleTaken; 
    } 

    public double Sample 
    { 
     get { return _sample; } 
     set 
     { 
     _sample = value; 
     OnPropertyChanged("Sample"); 
     } 
    } 

    public int StaleCount 
    { 
     get { return _staleCount; } 
     set 
     { 
     _staleCount = value; 
     OnPropertyChanged("StaleCount"); 
     } 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 

    private void _model_SampleTaken(object sender, SampleTakenEventArgs e) 
    { 
     if (e.SampleValue == Sample) 
     { 
     StaleCount++; 
     } 
     else 
     { 
     StaleCount = 0; 
     } 
     Sample = e.SampleValue; 
    } 

    protected void OnPropertyChanged(string propertyName) 
    { 
     var propertyChanged = PropertyChanged; 
     if (propertyChanged != null) 
     { 
     propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    } 
} 
0

警告:这是基于上述问题的破解,这是不理想的设计,但要做到的OP的目标。

你可以滑动您的当前绑定一个IMultiValueConverter,做这样的事情在XAML ...

<TextBlock Name="TextBlock"> 
    <TextBlock.Background> 
     <MultiBinding Converter="{StaticResource MyConverter}"> 
      <Binding Path="ViewModelProperty"></Binding> 
      <Binding ElementName="TextBlock"></Binding> 
     </MultiBinding> 
    </TextBlock.Background> 
    <TextBlock.Text> 
     <MultiBinding Converter="{StaticResource MyConverter}"> 
      <Binding Path="ViewModelProperty"></Binding> 
      <Binding ElementName="TextBlock"></Binding> 
     </MultiBinding> 
    </TextBlock.Text> 
</TextBlock> 

然后在IMultiValueConverter样本会...

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
{ 
    String text = (String)values[0]; 
    TextBlock reference = (TextBlock)values[1]; 

    if (targetType == typeof(String)) 
     return text; 
    else if (targetType == typeof(Brush)) 
    { 
     int count = 0; 
     if (reference.Tag == null) 
      reference.Tag = count; 

     count = (int)reference.Tag; 
     if (++count == 5) 
      return Brushes.Red; 
     else 
      return Brushes.White; 
    } 
    else 
     throw new NotSupportedException(); 
} 

我正在做的是利用你现有的财产,并将其实质性地超载,使你可以将TextBlock.Background财产绑定到ViewModel上已有的财产。请注意在MultiBinding中传递TextBlock实例的用法。

与此有关的警告是,如果您的设计正在通过实例移动计数将是不正确的,整个解决方案将有缺陷......不知道......在最初的问题没有足够的信息。再次,这是一个黑客攻击,如果你有更多的权限进行更改,有很多更好的方法来做到这一点。

+0

您的代码不起作用。如果您从转换器返回画笔,则会将文本框的文本设置为画笔,然后该画笔将显示“System.Drawing.SolidColorbrush”,作为画笔的.ToString()。 *绝对*不是原来的要求。 – 2010-10-19 22:49:30

+0

@Dan targetType正在被检查...如果它是一个字符串,这将是TextBox.Text属性,它将立即返回文本,如果targetType是Brush,这将是另一个绑定它将返回的Brush ... – 2010-10-19 22:58:14

+0

* *正在返回*画笔将设置文本框控件的文本为画笔。我怀疑你的意图是将文本框控件的背景设置为画笔,然后从转换器中返回原始字符串 - 但是无论如何,这是一个非常不好用的转换器。 – 2010-10-19 23:37:00

0

你可以改变DependencyProperty的实现吗?机会是你可以使用INotifyPropertyChanged作为一个属性实现它,如果你可以这样做,你将能够实现你需要的计数器逻辑。

从一个DependencyProperty回调不火的时候,价值不会改变,因此,如果您不能改变的实现,那么,就需要在其他地方钩码...

+0

任何理由这被投票下来? – 2010-10-19 23:37:33

0

感谢为了应对......我知道这是违背我们理想的设计......但是因为这已经与我们大部分的部分一起工作,最近客户改变了需求,因为想要打印这个值以及颜色也。

所以我有一种方法来解决它在属性元数据中使用强制回调而不是propertychnage事件。

已解决我的问题。现在我正在为我的单一控件执行此操作,并且需要此功能,现在我也能够获得常量值。

再次感谢