如何根据C#XAML WPF中另一个对象的状态更改一个对象的外观?

时间:2014-09-16 20:05:11

标签: c# wpf slideshow rectangles

我在主窗口的一系列网格中创建了幻灯片。目前有4张图片。幻灯片下方有3列。最后,我希望这些列中的内容随每张幻灯片而变化。目前,我使用矩形来表示内容。我希望矩形在显示每个图像时改变颜色(例如:当显示第一个图像时,矩形将是不同的红色阴影;当显示第二个图像时,矩形将是不同的蓝色阴影等)。我用来创建幻灯片的XAML是:

<Image x:Name="myImage" Stretch="Fill" MinHeight="400" MinWidth="500" Margin="5" 

ToolTip="SlideShow!"/>

以下是代码隐藏:

    public MainWindow()
    {
        InitializeComponent();
        Loaded += new RoutedEventHandler(MainWindow_Loaded);
    }

    public event EventHandler Tick;

    private DispatcherTimer tmr = new DispatcherTimer(); //Timer for Slide Show.
    private DispatcherTimer tmrPse = new DispatcherTimer(); //Timer for Pause, Last, and 
          //Next. Gives user time to view selected slide, and then re-starts tmr.

    private List<string> images = new List<string>();

    private int imageIndex = 0;

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
       tmr.Interval = new TimeSpan(0,0,2);
       tmr.Tick += new EventHandler(tmr_Tick);
       tmr.Start();

       tmrPse.Interval = new TimeSpan(0, 0, 5);
       tmrPse.Tick+= new EventHandler(tmrPse_Tick);

       LoadImages();

       ShowNextImage();

       ShowLastImage();
    }

    private void LoadImages()
    {
        // list the files (includede in the XAP file) here
        images.Add("/Images/AYDAYC.jpg"); //imageIndex = 0
        images.Add("/Images/CNNBert.jpg"); //imageIndex = 1
        images.Add("/Images/rwbjets.jpg"); //imageIndex = 2
        images.Add("/Images/worldmap.jpg"); //imageIndex = 3
    }

    private void ShowNextImage()
    {
        var bi = new BitmapImage(new Uri(images[imageIndex], UriKind.Relative));

        myImage.Source = bi;
        imageIndex = (imageIndex + 1) % images.Count;
    }

    private void ShowLastImage()
    {
        var bi = new BitmapImage(new Uri(images[imageIndex], UriKind.Relative));

        myImage.Source = bi;

        imageIndex = (imageIndex - 1) % images.Count;

        if (imageIndex < 0)
        {
            imageIndex = 3;
        }
     }

到目前为止,我已经找到了在鼠标点击时更改矩形或对象状态的方法,但不是按照我所描述的方式。我的幻灯片在计时器刻度上更改,但我也有按钮来停止计时器并前进,暂停或返回幻灯片。这些点击事件也会启动一个更长的计时器,允许所选幻灯片保持一段时间,之后原始计时器启动并恢复幻灯片放映(这就是为什么我喜欢要连接的矩形的状态每个幻灯片而不是计时器)。按钮和幻灯片完美无缺。我唯一的问题是如何在幻灯片图像和矩形之间建立关联。

2 个答案:

答案 0 :(得分:0)

您可以在矩形的背景颜色上使用Binding。在您的代码中,使用私有支持字段和公共getter和setter跟踪当前显示的Image Index的索引。后面的代码应该实现INotifyPropertyChanged来触发DataBinding。您的DataContext应设置为此值。所以页面的DataContext是页面本身(这样你可以绑定到页面上的属性,实际上是CurrentImageIndex左右)。然后使用ValueConverter绑定矩形的背景颜色。

一些伪代码:

Public class MainWindow: Page, INotifyPropertyChanged

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string name)
  {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
      {
          handler(this, new PropertyChangedEventArgs(name));
      }
  }

private Int16 _currentImageIndex;
public Int16 CurrentImageIndex{
  get{return _currentImageIndex;} 
  set
  {
    _currentImageIndex = value; 

    // fire PropertyChangedEventHandler
    OnPropertyChanged("CurrentImageIndex");
  }
}

public MainWindow()
{
  this.DataContext = this;
}

public class ImageIndexConverter: ValueConverter
{
  Convert
  {
    switch(value)
    {
      case 0: return Colors.Red;
      case 1: return Colors.Blue;
      //etc.
    }
  }

  ConvertBack
  {
    return null;
  }
}

XAML:

<Rectangle BackgroundColor={Binding Path=CurrentImageIndex, Converter={StaticResource ImageIndexConverter}}/>

没有测试代码,但我希望这个概念对你来说很清楚。看看INotifyPropertyChanged和ValueConverter的概念。

答案 1 :(得分:-1)

我找到了一种更简单的方法。由于幻灯片基于imageIndex的值而改变,我创建了一个名为BoxColor的方法,其中包含if语句,该语句根据该值更改框的颜色。然后,我在计时器刻度事件和按钮单击事件中调用该方法以推进幻灯片并返回幻灯片:

    public MainWindow()
    {
        InitializeComponent();
        Loaded += new RoutedEventHandler(MainWindow_Loaded);
    }

    public event EventHandler Tick;        

    private DispatcherTimer tmr = new DispatcherTimer(); //Timer for Slide Show.
    private DispatcherTimer tmrPse = new DispatcherTimer(); //Timer for click events.

    private List<string> images = new List<string>();        

    public int imageIndex =-1; //Determines which slide to show.        

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        tmr.Interval = new TimeSpan(0, 0, 2);
        tmr.Tick += new EventHandler(tmr_Tick);

        tmrPse.Interval = new TimeSpan(0, 0, 5);
        tmrPse.Tick += new EventHandler(tmrPse_Tick);

        LoadImages();

        tmr.Start();
    }

    private void LoadImages()
    {
        // list the files (includede in the XAP file) here
        images.Add("/Images/AYDAYC.jpg"); //imageIndex = 0
        images.Add("/Images/CNNBert.jpg"); //imageIndex = 1
        images.Add("/Images/rwbjets.jpg"); //imageIndex = 2
        images.Add("/Images/worldmap.jpg"); //imageIndex = 3
    }

    private void ShowNextImage()
    {
        imageIndex = (imageIndex + 1) % images.Count;

        var bi = new BitmapImage(new Uri(images[imageIndex], UriKind.Relative));

        myImage.Source = bi;
    }

    private void ShowLastImage()
    {
        imageIndex = (imageIndex - 1);

        if (imageIndex < 0)
        {
            imageIndex = 3;
        }

        var bi = new BitmapImage(new Uri(images[imageIndex], UriKind.Relative));

        myImage.Source = bi;
    }

    private void BoxColor()
    {
        if (imageIndex == 3)
        {
            LftRct.Fill = new SolidColorBrush(Colors.Green);
            MidRct.Fill = new SolidColorBrush(Colors.SpringGreen);
            RtRct.Fill = new SolidColorBrush(Colors.PaleGreen);
        }

        else if (imageIndex == 2)
        {
            LftRct.Fill = new SolidColorBrush(Colors.Blue);
            MidRct.Fill = new SolidColorBrush(Colors.RoyalBlue);
            RtRct.Fill = new SolidColorBrush(Colors.SkyBlue);
        }

        else if (imageIndex == 1)
        {
            LftRct.Fill = new SolidColorBrush(Colors.White);
            MidRct.Fill = new SolidColorBrush(Colors.Silver);
            RtRct.Fill = new SolidColorBrush(Colors.SlateGray);
        }

        else
        {
            LftRct.Fill = new SolidColorBrush(Colors.Red);
            MidRct.Fill = new SolidColorBrush(Colors.Tomato);
            RtRct.Fill = new SolidColorBrush(Colors.Pink);
        }            
    }

    void tmr_Tick(object sender, EventArgs e)
    {
        ShowNextImage();
        BoxColor();
    }

    void tmrPse_Tick(object sender, EventArgs e)
    {                      
        tmr.Start();
    }

    private void btnLast_Click(object sender, RoutedEventArgs e)
    {
        tmr.Stop();
        tmrPse.Start();
        ShowLastImage();
        BoxColor();                      
    }

    private void btnPause_Click(object sender, RoutedEventArgs e)
    {            
        tmr.Stop();
        tmrPse.Start();                       
    }       

    private void btnNext_Click(object sender, RoutedEventArgs e)
    {
        tmr.Stop();
        tmrPse.Start();
        ShowNextImage();
        BoxColor();
     }       

我可能会将逻辑切换到开关,使其更整洁。不过,这是学习自定义事件处理程序的一个很好的练习。