2010-12-20 60 views
0

我需要一个答案,所以我可以探索。我遇到一个砖墙的位置:WPF - 数据绑定颜色为简单的简单窗口或画布在窗口背景 - 无控件

我想用:

 for (int c = 0; c < 255; c++) 
     { 

      Color = Color.FromArgb(255, (byte)c, (byte)(255 - c), (byte)c); 
      Thread.Sleep(3); 
     } 

每一次“颜色”重新计算,我想在窗口或画布在窗口立即改变颜色...所以我看到了很酷的颜色变化。为什么这么难?我需要看到这一点,但我正在打砖墙。我在这里复制了一个类型转换器:

[ValueConversion(typeof(Color),typeof(SolidColorBrush))] 
public class ColorBrushConverter : IValueConverter 
{ 


    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     Color color = (Color)value; 
     return new SolidColorBrush(color); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return null; 
    } 

} 

谢谢你的任何帮助!

回答

0

你正在UI线程中这样做。如果您用Thread.Sleep阻止UI线程,则UI块也会(并且不会应用更改)。

解决方法是使用Timer而不是循环。在窗口的某个实例变量中保存c。设置一个在3ms后过期的计时器,增加c,更改Color,然后重置计时器以在3 ms内再次关闭。

或者,您可以启动后台线程循环(并使用Thread.Sleep)。在这种情况下,您必须通过Dispatcher.Invoke应用颜色更改,而不是简单设置Color = ...


为了说明我的观点,在这里有一个如何与后台线程做一个简单的例子:

// define the background thread 
var colorChangeThread = new Thread(new ThreadStart(() => { 
    for (int c = 0; c < 255; c++) 
    { 
     // this (and only this) is done in the UI thread 
     Dispatcher.Invoke(new Action(() => { 
      this.Background = new SolidColorBrush(Color.FromArgb(255, (byte)c, (byte)(255 - c), (byte)c)); 
     })); 

     Thread.Sleep(8); // the background thread waits 
    } 
})); 
colorChangeThread.Start(); // start the background thread 

如果您使用的是带有INotifyPropertyChanged的属性,您可以跳过Dispatcher.Invoke和公正设置你的财产,请参阅Meleaks答案中的解释。

+0

你好,谢谢你的回答。我正在寻找基本的管道。我可以做计时器的事情,所以颜色不会改变太快,我看不到他们。我无法让背景动态改变颜色。 – woops 2010-12-20 19:22:12

+0

@woops:我真的不明白......定时器方法的问题在哪里? – Heinzi 2010-12-20 19:23:58

+0

它不是定时器方法。完全从图片中取出计时器。如何将代码中生成的颜色绑定到window.background或canvas.background,并立即更新屏幕以显示新的颜色背景? – woops 2010-12-20 19:33:08

0

一个简单的例子,说明如何将颜色属性从代码背后绑定到画布背景。注意事项

  • 实施INotifyPropertyChanged。 Canvas的背景将在OnPropertyChanged上更新,每次MyColorProperty更改时都会执行。
  • 设置DataContext = this;在构造函数中将使Window中的所有控件继承此DataContext(除非这被覆盖)。

XAML

<Canvas ...> 
    <Canvas.Background> 
     <SolidColorBrush Color="{Binding MyColorProperty}"/> 
    </Canvas.Background> 

代码背后

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     this.DataContext = this; 
    } 

    // ... 

    private Color m_myColorProperty; 
    public Color MyColorProperty 
    { 
     get 
     { 
      return m_myColorProperty; 
     } 
     set 
     { 
      m_myColorProperty = value; 
      OnPropertyChanged("MyColorProperty"); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    private void SwitchBackground() 
    { 
     if (MyColorProperty == Colors.Red) 
     { 
      MyColorProperty = Colors.Black; 
     } 
     else 
     { 
      MyColorProperty = Colors.Red; 
     } 
    } 
} 

更新
要运行的背景动画,你可以使用一个BackgroundWorker这样

private BackgroundWorker m_changeColorBgWorker = null; 

public MainWindow() 
{ 
    InitializeComponent(); 
    this.DataContext = this; 
    m_changeColorBgWorker = new BackgroundWorker(); 
    m_changeColorBgWorker.DoWork += new DoWorkEventHandler(m_changeColorBgWorker_DoWork); 
} 
private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    if (m_changeColorBgWorker.IsBusy == false) 
    { 
     m_changeColorBgWorker.RunWorkerAsync(); 
    } 
} 
void m_changeColorBgWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while (true) 
    { 
     for (int c = 0; c < 254; c++) 
     { 
      MyColorProperty = Color.FromArgb(255, (byte)c, (byte)(255 - c), (byte)c); 
      Thread.Sleep(10); 
     } 
    } 
} 

您可以直接在线程中设置MyColorProperty,因为INotifyPropertyChanged触发的更改会自动整理回调度程序。但是,这并不适用于INotifyCollectionChanged,只是你知道的。

+0

这很好用!现在,如果我想运行这个: – woops 2010-12-20 21:23:18

+0

while(true) {int c = 0; c <254; C++) {0} MyColorProperty = Color.FromArgb(255,(byte)c,(byte)( 255-c),(字节)c); } } – woops 2010-12-20 21:23:48

+0

如何在每次更改财产后更新窗口? – woops 2010-12-20 21:24:12