0

我需要一个答案,以便我可以探索。我在这里遇到了一堵砖墙:

我想使用:

        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;
    }

}

感谢您的任何帮助!

4

2 回答 2

0

您正在 UI 线程中执行此操作。如果您使用 阻塞 UI 线程Thread.Sleep,UI 也会阻塞(并且不会应用任何更改)。

解决方案是使用 Timer 而不是循环。保存c在窗口的某个实例变量中。设置一个在 3 ms 后到期的计时器,增加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 答案中的说明。

于 2010-12-20T18:37:39.620 回答
0

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

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

xml

<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,您知道。

于 2010-12-20T20:27:34.020 回答