C# 我的图像滑块代码的PropertyChanged事件为';他没有被养大
我正在尝试用本机WPF控件实现一个图像滑块。单击“下一步”、“上一步”或“添加新属性”时,所选索引和当前图像属性的C# 我的图像滑块代码的PropertyChanged事件为';他没有被养大,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我正在尝试用本机WPF控件实现一个图像滑块。单击“下一步”、“上一步”或“添加新属性”时,所选索引和当前图像属性的PropertyChanged事件未触发 视图模型: namespace WpfApplication2.ImageSlider { public class ImageList : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged;
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();
}
}
}
XAML:
你弄错了。。。。这就是它不起作用的原因 属性已更改不要设置值,只有信号系统才能从属性中获取值 作为新的ImageListClass尝试此选项 `
公共类ImageListFixed:INotifyPropertyChanged
{
#区域字段
私有ObservableCollection图像=新ObservableCollection();
私有int-selectedIndex;
私有图像项当前图像;
#端域字段
#区域属性
公众可观测采集图像
{
获取{返回图像;}
设置{images=value;}
}
公共整数选择索引
{
获取{return selectedIndex;}
设置
{
如果(值-1)
{
selectedIndex=value;OnPropertyChanged();
CurrentImage=图像[selectedIndex];
}
}
}
公共图像项目当前图像
{
获取{return currentImage;}
设置{currentImage=value;OnPropertyChanged();}
}
#端域属性
#区域公共方法
下一个公共空间()
{
选择dex++;
}
公众退票()
{
选择索引--;
}
#端域公共方法
#区域方法
public void AddNewImage()
{
OpenFileDialog dlg=新建OpenFileDialog();
dlg.Filter=“图像文件(*.jpg,*.jpeg,*.jpe,*.gif,*.png,*.bmp,*.tif)|*.jpg;*.jpeg;*.jpe;*.gif;*.png,*.bmp,*.tif”;
dlg.ShowDialog();
如果(dlg.FileName!=“”)
{
Add(newImageItem(){URI=newURI(dlg.FileName)});
SelectedIndex=Images.Count-1;
}
}
#端域法
#区域构造函数
公共ImageListFixed()
{
_canExecute=true;
}
#端域构造函数
#区域命令
专用ICommand_clickCommand;
公共ICommand ClickCommand
{
得到
{
返回_clickCommand??(_clickCommand=newcommandHandler(()=>AddNewImage(),_canExecute));
}
}
私人楼宇可执行;
私有ICommand下一个命令;
公共ICommand下一个命令
{
得到
{
if(nextCommand==null)
{
nextCommand=newcommandhandler(()=>OnNextCommand(),true);
}
返回下一个命令;
}
设置{nextCommand=value;}
}
私有void OnNextCommand()
{
Next();
}
私有ICommand backCommand;
公共ICommand back命令
{
得到
{
if(backCommand==null)
{
backCommand=newcommandhandler(()=>OnBackCommand(),true);
}
返回返回命令;
}
设置{backCommand=value;}
}
私有void OnBackCommand()
{
背();
}
#endregion命令
#区域inotifyproperty已更改
公共事件属性更改事件处理程序属性更改;
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
#endregion InotifyProperty已更改
}`
删除窗口中的所有后台代码,并将窗口代码更改为以下内容:
<DockPanel>
<Button Content="<" Command="{Binding BackCommand}"/>
<Button DockPanel.Dock="Right" Content=">" Command="{Binding NextCommand}"/>
<Image Source="{Binding CurrentImage.Source, Mode=OneWay}"/>
<Button Content="Add" Command="{Binding ClickCommand}"></Button>
</DockPanel>
问题在于,按钮使用的
ImageList
对象与图像显示使用的对象不同。您已经在XAML中将ImageList
的一个新实例声明为DataContext
对象。您的代码隐藏确实尝试将此对象分配给\u list
字段,该字段支持您用来调用Back()
和Next()
方法的list
属性
但是这种分配字段的尝试是错误的代码,甚至不会起作用,因为从来没有人调用属性的setter。因此getter总是返回您在字段初始值设定项中分配的空ImageList
对象
您应该只提供一个getter并强制转换DataContext
值:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public ImageList list
{
get { return (ImageList)DataContext; }
}
private void Next_Click(object sender, RoutedEventArgs e)
{
list.Next();
}
private void Back_Click(object sender, RoutedEventArgs e)
{
list.Back();
}
}
我认为这可能是因为您的DataContext没有设置为包含处理程序的MainWindow实例。您具体说的“不触发”是什么意思?单击第一个按钮时,您发布的代码将调用例如
Back\u Click()
方法,该方法将调用list.Back()
方法。你发布的代码中没有任何东西可以阻止这一点。但你的问题中没有任何东西表明你可能在问其他问题。在任何情况下,如果您的问题是关于事件的,那么您不需要发布多个按钮或实际图像来重现“不触发”行为。请提供一个很好的例子,并准确地解释问题是什么。@PeterDuniho我在代码中提到了确切的问题发生的地方PropertyChanged
为null,并且未激发CurrentImageProperty
。好的,谢谢。你的问题根本不清楚(包括代码中关于null
值的隐晦注释),但我已经编辑了你的标题和问题,使其现在变得清晰,并提供了问题的答案(我不同意另一个答案,至少就眼前的问题而言).我用的是C版本<6。你能改进一下这个吗<代码>PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName))代码>大多数这只是一个偏好问题,而不是功能问题,用命令绑定取代事件处理,两者都是wor
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();
}
}
public class ImageListFixed : INotifyPropertyChanged
{
#region Fields
private ObservableCollection<ImageItem> images = new ObservableCollection<ImageItem>();
private int selectedIndex;
private ImageItem currentImage;
#endregion Fields
#region Properties
public ObservableCollection<ImageItem> Images
{
get { return images; }
set { images = value; }
}
public int SelectedIndex
{
get { return selectedIndex; }
set
{
if(value < Images.Count && value > -1)
{
selectedIndex = value; OnPropertyChanged();
CurrentImage = Images[selectedIndex];
}
}
}
public ImageItem CurrentImage
{
get { return currentImage; }
set { currentImage = value; OnPropertyChanged(); }
}
#endregion Properties
#region Public Methods
public void Next()
{
SelectedIndex ++;
}
public void Back()
{
SelectedIndex--;
}
#endregion Public Methods
#region Methods
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) });
SelectedIndex = Images.Count - 1;
}
}
#endregion Methods
#region Constructors
public ImageListFixed()
{
_canExecute = true;
}
#endregion Constructors
#region Commands
private ICommand _clickCommand;
public ICommand ClickCommand
{
get
{
return _clickCommand ?? (_clickCommand = new CommandHandler(() => AddNewImage(), _canExecute));
}
}
private bool _canExecute;
private ICommand nextCommand;
public ICommand NextCommand
{
get
{
if (nextCommand == null)
{
nextCommand = new CommandHandler(()=> OnNextCommand(), true);
}
return nextCommand;
}
set { nextCommand = value; }
}
private void OnNextCommand()
{
Next();
}
private ICommand backCommand;
public ICommand BackCommand
{
get
{
if(backCommand == null)
{
backCommand = new CommandHandler(() => OnBackCommand(), true);
}
return backCommand;
}
set { backCommand = value; }
}
private void OnBackCommand()
{
Back();
}
#endregion Commands
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion INotifyPropertyChanged
}`
<DockPanel>
<Button Content="<" Command="{Binding BackCommand}"/>
<Button DockPanel.Dock="Right" Content=">" Command="{Binding NextCommand}"/>
<Image Source="{Binding CurrentImage.Source, Mode=OneWay}"/>
<Button Content="Add" Command="{Binding ClickCommand}"></Button>
</DockPanel>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public ImageList list
{
get { return (ImageList)DataContext; }
}
private void Next_Click(object sender, RoutedEventArgs e)
{
list.Next();
}
private void Back_Click(object sender, RoutedEventArgs e)
{
list.Back();
}
}