【问题标题】:wpf button change image sourcewpf按钮更改图像源
【发布时间】:2013-11-28 09:15:05
【问题描述】:

我编写 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;

【问题讨论】:

    标签: wpf image button


    【解决方案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 for 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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-05
      • 2016-07-12
      • 2019-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多