【发布时间】:2016-07-27 05:52:22
【问题描述】:
我正在尝试使用本机 WPF 控件实现图像滑块。当我单击 Next 或 Back 或 Add a new 时,SelectedIndex 和 CurrentImage 属性的 PropertyChanged 事件不会触发。
视图模型:
namespace WpfApplication2.ImageSlider
{
public class ImageList : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<ImageItem> _Images = new ObservableCollection<ImageItem>();
public ObservableCollection<ImageItem> Images
{
get
{ return _Images; }
}
private int _SelectedIndex;
public static readonly PropertyChangedEventArgs SelectedIndexProperty = new PropertyChangedEventArgs("SelectedIndex");
public int SelectedIndex
{
get { return _SelectedIndex; }
set
{
_SelectedIndex = value;
var handler = PropertyChanged; // value is null
if (handler != null)
{
handler(this, SelectedIndexProperty);
handler(this, CurrentImageProperty);
}
}
}
public static readonly PropertyChangedEventArgs CurrentImageProperty = new PropertyChangedEventArgs("CurrentImage"); //Not Firing
private ImageItem _CurrentImage;
public ImageItem CurrentImage //Not Firing
{
get { return _CurrentImage; }
set
{
_CurrentImage = value;
if (Images.Count > 0)
{
CurrentImage =
Images[SelectedIndex];
}
}
}
public void Next()
{
if (SelectedIndex < Images.Count - 1)
SelectedIndex++;
else
SelectedIndex = 0;
}
public void Back()
{
if (SelectedIndex == 0)
SelectedIndex = Images.Count - 1;
else
SelectedIndex--;
}
private ICommand _clickCommand;
public ICommand ClickCommand
{
get
{
return _clickCommand ?? (_clickCommand = new CommandHandler(() => AddNewImage(), _canExecute));
}
}
public ImageList()
{
_canExecute = true;
}
private bool _canExecute;
public void AddNewImage()
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.gif, *.png, *.bmp, *.tif) | *.jpg; *.jpeg; *.jpe; *.gif; *.png, *.bmp, *.tif";
dlg.ShowDialog();
if (dlg.FileName != "")
{
Images.Add(new ImageItem() { URI = new Uri(dlg.FileName) });
var handler = PropertyChanged;
if (handler != null)
{
handler(this, CurrentImageProperty);
}
}
}
}
public class CommandHandler : ICommand
{
private Action _action;
private bool _canExecute;
public CommandHandler(Action action, bool canExecute)
{
_action = action;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_action();
}
}
}
型号:
namespace WpfApplication2.ImageSlider
{
public class ImageItem
{
public Uri URI { get; set; }
private BitmapSource _Source;
public BitmapSource Source
{
get
{
try
{
if (_Source == null) _Source = new BitmapImage(URI);//lazy loading
}
catch (Exception)
{
_Source = null;
}
return _Source;
}
}
public void Save(string filename)
{
var img = BitmapFrame.Create(Source);
var encoder = new JpegBitmapEncoder();
encoder.Frames.Add(img);
using (var saveStream = System.IO.File.OpenWrite(filename))
encoder.Save(saveStream);
}
}
}
XAML:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication2.ImageSlider"
mc:Ignorable ="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<BitmapImage x:Key="NotFound" UriSource="E:\..\NotFound.png"/>
</Window.Resources>
<Window.DataContext>
<local:ImageList/>
</Window.DataContext>
<DockPanel>
<Button Content="<" Click="Back_Click"/>
<Button DockPanel.Dock="Right" Content=">" Click="Next_Click"/>
<Image Source="{Binding CurrentImage.Source, Mode=OneWay,
TargetNullValue={StaticResource NotFound},
FallbackValue={StaticResource NotFound}}"/>
<Button Content="Add" Command="{Binding ClickCommand}"></Button>
</DockPanel>
</Window>
XAML.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private ImageList _list= new ImageList();
public ImageList list
{
get { return _list; }
set { _list = DataContext as ImageList; } //The count of the images is always 0;
}
private void Next_Click(object sender, RoutedEventArgs e)
{
list.Next();
}
private void Back_Click(object sender, RoutedEventArgs e)
{
list.Back();
}
}
【问题讨论】:
-
我认为这可能是因为您的 DataContext 未设置为包含处理程序的 MainWindow 实例。
-
你说的“不开火”具体是什么意思?您发布的代码将调用例如当点击第一个按钮时,
Back_Click()方法,该方法将调用list.Back()方法。您发布的代码中没有任何内容可以阻止这种情况。但是您的问题中没有任何内容表明您可能会问其他问题。无论如何,如果您的问题是关于事件的,那么您无需发布多个按钮或实际图像即可重现“未触发”行为。请提供一个好的minimal reproducible example,并准确解释问题所在。 -
@PeterDuniho 我已经在发生确切问题的代码中提到。
PropertyChanged为空,CurrentImageProperty不会被解雇。 -
好的,谢谢。您的问题对此一无所知(包括代码中关于
null值的神秘评论),但我已经编辑了您的标题和问题,以便现在清楚,并提供了问题的答案(我不同意另一个答案,至少就手头的直接问题而言)。