提问人:BugsFree 提问时间:11/17/2023 最后编辑:BugsFree 更新时间:11/17/2023 访问量:35
WPF - 以编程方式更改它的图像可视化效果错误
WPF - Wrong image visualization changing it programmatically
问:
我有两个窗口:
- MainWindow 在 DataGrid 中加载图像并显示它们的预览
- 双击 DataGrid 中显示相关图像的行时,将打开 ImageWindow
我想说的是,当 ImageWindow 打开时,用户按下左键或右键按钮,ImageWindow 将分别加载 DataGrid 中的上一个或下一个图像。
这是我到目前为止所做的:
ImageWindow.xaml
<Window x:Class="ImageBrowser.ImageWindow"
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:ImageBrowser"
xmlns:local1="clr-namespace:ImageBrowser.Controls"
mc:Ignorable="d"
Title="ImageWindow" KeyDown="Window_KeyDown" SourceInitialized="Window_SourceInitialized" WindowStartupLocation="CenterScreen">
<Grid x:Name="GridContainer" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="ClosedCurveButton" Grid.Column="0" Background="LightBlue" ToolTip="Draw closed curve" Click="ClosedCurveButton_Click" HorizontalAlignment="Left">
<Image Source="/Resources/spline.png"/>
</Button>
<Button x:Name="ClosedCurveInfoButton" Grid.Column="2" Background="LightBlue" ToolTip="Show curves info" Click="ClosedCurveInfoButton_Click" HorizontalAlignment="Left">
<Image Source="/Resources/statistic.png"/>
</Button>
</Grid>
<Canvas Grid.Row="1" x:Name="canvasContainer" Height="{Binding ElementName=currentImg, Path=ActualHeight}" Width="{Binding ElementName=currentImg, Path=ActualWidth}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image x:Name="currentImg" Source="{Binding ImageBpm}" Mouse.MouseEnter="CurrentImg_MouseEnter" Mouse.MouseLeave="CurrentImg_MouseLeave"
Mouse.MouseMove="CurrentImg_MouseMove" ContextMenuOpening="CurrentImg_ContextMenuOpening" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Loaded="Window_Loaded">
<Image.ContextMenu>
<ContextMenu>
<MenuItem Header="Set LandMark" Click="AddLandMark_Click" CommandParameter="{Binding MousePosition}"/>
</ContextMenu>
</Image.ContextMenu>
</Image>
</Canvas>
<Label x:Name="CoordinatesLabel" Grid.Row="2" Visibility="Hidden" FontSize="14" HorizontalAlignment="Left">Image Ref x: {0} y:{1} - Grid Ref x: {2} y:{3}</Label>
</Grid>
图像窗口.cs
public partial class ImageWindow : Window, INotifyPropertyChanged
{
private MainWindow _parent;
public event EventHandler GoPrevius;
public event EventHandler GoNext;
private BitmapImage _imageBpm;
public BitmapImage ImageBpm
{
get { return _imageBpm; }
set
{
if (_imageBpm != value)
{
_imageBpm = value;
OnPropertyChanged(nameof(ImageBpm));
}
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
public ImageWindow(MainWindow parent, string imageName)
{
InitializeComponent();
Title = imageName;
_parent = parent;
_parent.NewImage += _parent_NewImage;
DataContext = this;
}
private void _parent_NewImage(object sender, NewImageEventArgs e)
{
RemoveLandMarks();
ImageBpm = CreateImageSource(e.NewImageName);
Title = e.NewImageName;
ReloadLandMark(_parent.ImagesMap[Title]);
}
private BitmapImage CreateImageSource(string imageName = "")
{
string image = imageName.Equals("") ? Title : imageName;
BitmapImage bitmapImage = new BitmapImage();
try
{
using (MemoryStream memoryStream = new MemoryStream(_parent.ImagesMap[Title].ImageBytes))
{
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = memoryStream;
memoryStream.Position = 0;
bitmapImage.EndInit();
}
}
catch (Exception ex)
{
MessageBox.Show($"Error loading image: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
return bitmapImage;
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Left)
{
GoPrevius?.Invoke(this, new EventArgs());
}
else if (e.Key == Key.Right)
{
GoNext?.Invoke(this, new EventArgs());
}
}
}
MainWindow.xaml.cs
public class NewImageEventArgs : EventArgs
{
public string NewImageName { get; set; }
public NewImageEventArgs(string newImageName)
{
NewImageName = newImageName;
}
}
public partial class MainWindow : Window
{
public Dictionary<string, LandMarkedImage> ImagesMap { get; } = new Dictionary<string, LandMarkedImage>();
public event EventHandler<NewImageEventArgs> NewImage;
private void ImageWindow_GoNext(object sender, EventArgs e)
{
if (ImageGrid.Items.Count - 1 > ImageGrid.SelectedIndex)
{
ImageGrid.SelectedIndex++;
Item item = ImageGrid.SelectedItem as Item;
NewImage?.Invoke(this, new NewImageEventArgs(item.Name));
}
}
private void ImageWindow_GoPrevius(object sender, EventArgs e)
{
if (ImageGrid.SelectedIndex > 0)
{
ImageGrid.SelectedIndex--;
Item item = ImageGrid.SelectedItem as Item;
NewImage?.Invoke(this, new NewImageEventArgs(item.Name));
}
}
}
我得到的奇怪行为是,当我第一次按下向左或向右按钮时,图像没有改变。我确信事件被正确触发,因为我在调试中遵循了,并且因为 ImageWindow 的标题更改了新图像的名称,但图像本身没有遵循。
我读到这可能与BitmapImage的“激进”缓存有关,所以我尝试使用该标志,但随后软件开始崩溃,抛出缺少键的异常。我发现阅读这个答案我不能使用该标志,因为似乎只有当图像是从 URI 加载时才能使用它。BitmapCreateOptions.IgnoreImageCache
答: 暂无答案
评论