2013-11-15 4 views
1

I код приложения wpf. У меня есть большая схема со многими кнопками, которые созданы и появились динамично. Когда пользователь нажимает на кнопки, его изображения также должны меняться динамически. Но у меня проблема: когда изображение кнопки было изменено, прошлое изображение осталось на сетке. Как я могу правильно изменить изображение кнопки или удалить оставшееся изображение?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); 
    } 

Этого код для удаления прошлого изображения из кнопки, которые находились на сетке и supperimposed на новом изображении кнопки:

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; 

ответ

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; 
} 

Вашего изображения Del Эфирный код полностью избыточен. Убрать все это:

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(); 
Смежные вопросы