我编写了wpf应用程序代码。我有一个很大的计划,有许多按钮创建和动态出现。当用户单击按钮时,其图像也必须动态更改。但是我遇到了一个问题:当按钮图像被更改时,过去的图像停留在网格上。 如何正确更改按钮图像,或删除保留的图像?
这是我的xaml文件:
<Grid x:Name="MainGrid">
<ScrollViewer x:Name="MainScroll" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas x:Name="InCanvas" Width="{Binding ActualWidth, ElementName=imageMnemoScheme}" Height="{Binding ActualHeight, ElementName=imageMnemoScheme}">
<Image x:Name="imageMnemoScheme" RenderOptions.BitmapScalingMode="HighQuality" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" Source="pack://siteoforigin:,,,/images/mnemoscheme.bmp" Stretch="None" />
</Canvas>
</ScrollViewer>
</Grid>
我需要ScrollViewer,因为方案非常大。
这是动态创建的按钮的样式:
<Window.Resources>
<Style x:Key="NoChromeButton" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="BorderBrush" Value="White" />
</Style>
</Window.Resources>
以下是创建按钮的代码:
private ImageSource BitmapFromImagePath(string path)
{
byte[] imageData;
using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
using (BinaryReader binaryReader = new BinaryReader(fileStream))
{
imageData = binaryReader.ReadBytes((int)fileStream.Length);
}
}
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
MemoryStream st = new MemoryStream(imageData);
bitmap.StreamSource = st;
bitmap.EndInit();
return bitmap;
}
private void MakeImage(Point pos, int objType, int objState, int objOrientation, int objColor)
{
Image xz = new Image();
xz.Source = BitmapFromImagePath(GetImagePathByType(objType, objState, objOrientation, objColor));
xz.Stretch = Stretch.Uniform;
Button b = new Button();
b.Style = style;
b.Content = xz;
b.Click += new RoutedEventHandler(ObjectImageClick);
InCanvas.Children.Add(b);
}
此代码用于从按钮中删除过去的图像,该图像保留在网格上并在新按钮图像上显示:
Image xz = (Image)myB.Content;
BitmapImage bi = (BitmapImage)xz.Source;
MemoryStream ms = (MemoryStream)bi.StreamSource;
ms.FlushAsync();
ms.Close();
ms.Dispose();
myB.Content = null;
xz.Source = null;
bi.StreamSource = null;
ms = null;
bi = null;
xz = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Image smth = new Image();
smth.Source = BitmapFromImagePath(GetImagePathByType(objType, newObjState, objOrientation, objColor));
smth.Stretch = Stretch.Uniform;
myB.Content = smth;
答案 0 :(得分:1)
显然,您永远不会从InCanvas
删除任何按钮,或者至少我可以在您的问题中找到任何相关代码。
您可以在MakeImage
中添加新按钮之前清除画布:
InCanvas.Children.Clear();
InCanvas.Children.Add(b);
除此之外,您的代码太复杂了。从文件加载图像不需要比这更多的代码:
private ImageSource BitmapFromImagePath(string path)
{
return BitmapFrame.Create(new Uri(path));
}
如果由于某种原因你需要手动阅读文件(例如,如果你想在阅读后立即删除它):
private ImageSource BitmapFromImagePath(string path)
{
using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
return BitmapFrame.Create(
fileStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
}
从路径字符串创建ImageSource的最安全或最简单的方法是使用内置TypeConverter
ImageSource
:
private ImageSource BitmapFromImagePath(string path)
{
var converter = new System.Windows.Media.ImageSourceConverter();
return converter.ConvertFrom(path) as ImageSource;
}
您的图片删除代码完全是多余的。删除所有这些:
Image xz = (Image)myB.Content;
BitmapImage bi = (BitmapImage)xz.Source;
MemoryStream ms = (MemoryStream)bi.StreamSource;
ms.FlushAsync();
ms.Close();
ms.Dispose();
myB.Content = null;
xz.Source = null;
bi.StreamSource = null;
ms = null;
bi = null;
xz = null;
GC.Collect();
GC.WaitForPendingFinalizers();