前景:本人大四毕业党一枚,毕业设计导师要求做一个可以控制图片旋转的桌面程序,用的是WPF....但本人学的是Java,WPF表示没怎么接触过,最近遇到一个棘手的问题,调了两天了,也没有调好,所以特来求助!
Ok,话不多说,上代码!
这是我的窗体代码(只是一个Demo):
<Window x:Class="ImageRotate.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <!-- <Canvas x:Name="testCanvs" Height="280" Width="490" Background="AliceBlue"></Canvas> --> <Image Name="myG" Height="200" Width="200" Source="Picture\frontView.png"> <Image.RenderTransform> <RotateTransform Angle="{Binding Path=Angle}" CenterX="100" CenterY="100" /> </Image.RenderTransform> </Image> </Window>
后台用的C#,是这样的:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; using ImageRotate; namespace ImageRotate { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { Image images; Test test; float a = 0.0f; Test t = new Test(); public MainWindow() { InitializeComponent(); //ImageRotate(); DispatcherTimer dispatcher = new DispatcherTimer(); dispatcher.Tick += new EventHandler(dispatcherTimer); dispatcher.Interval = TimeSpan.FromMilliseconds(1000); dispatcher.Start(); t.Angle = a; Binding bin = new Binding(); bin.Source = t; bin.Path = new PropertyPath("Angle"); RotateTransform rt = new RotateTransform(); BindingOperations.SetBinding(rt, RotateTransform.AngleProperty, bin); } private void dispatcherTimer(object sender, EventArgs e) { Console.Write(" "+a); a =a+ 0.2f; } /** private void ImageRotate() { images = new Image(); images.Width = 150; images.Height = 150; TransformedBitmap tb = new TransformedBitmap(); BitmapImage bi = new BitmapImage(); bi.BeginInit(); bi.UriSource = new Uri(@"Picture\frontView.png", UriKind.RelativeOrAbsolute); bi.EndInit(); tb.BeginInit(); tb.Source = bi; RotateTransform tramforms = new RotateTransform(45); tb.Transform = tramforms; tb.EndInit(); images.Source = tb; } */ } }
还有一个Test的类如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel; using System.Windows.DependencyProperty; namespace ImageRotate { class Test :INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; double _Angle; public double Angle { get { return _Angle; } set { _Angle = value; //这里就是报错的地方! PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Angle")); } } } }
每次运行的时候就是报错!
求助啊!各路大牛,各路神仙们!小弟感激不尽!!!!!
试了一下你的代码,这个错误的原因是出在如下地方
PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Angle"));
使用事件前没有判空,当前事件没有订阅的时候就抛出了空引用异常,正确的方式是
if (PropertyChanged != null) PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Angle"));
但是,即使这么写,只是不抛异常而已,你的程序本身就有很多地方有遗漏,简单的修改了一下,你可以参考下:
public MainWindow() { InitializeComponent(); //ImageRotate(); DispatcherTimer dispatcher = new DispatcherTimer(); dispatcher.Tick += new EventHandler(dispatcherTimer); dispatcher.Interval = TimeSpan.FromMilliseconds(1000); dispatcher.Start(); t.Angle = a; Binding bin = new Binding(); bin.Source = t; bin.Path = new PropertyPath("Angle"); RotateTransform rt = new RotateTransform(); BindingOperations.SetBinding(rt, RotateTransform.AngleProperty, bin); myG.RenderTransform = rt; //没有应用该Transfrorm } private void dispatcherTimer(object sender, EventArgs e) { Console.Write(" " + a); a = a + 10f; t.Angle = a; //没有更新Angle值 } Image images; Test test; float a = 0.0f; Test t = new Test(); } class Test : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; double _Angle; public double Angle { get { return _Angle; } set { _Angle = value; //这里就是报错的地方! if (PropertyChanged != null) //没有判断是否订阅了事件 PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Angle")); } } }
最后说明的是,如果你是要做动画效果的话,这种方式是不正确的,应该使用DoubleAnimation。 当然,你也可以简单的将你现在的代码中的Timer的间隔调整到100ms来实现类似的效果。