سؤال

لدي مشكلة غريبة مع WPF، كنت جرس الصور من القرص في وقت التشغيل وإضافةها إلى حاوية StackView. ومع ذلك، لم يتم عرض الصور. بعد بعض تصحيح الأخطاء وجدت الحيلة، لكنها حقا لا معنى لها. لقد قمت بإجراء تطبيق تجريبي صغير لتحديد المشكلة:

إنشاء مشروع WPF جديد، ورمز لصق كما يلي:

XAML:

<Window x:Class="wpfBug.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">
    <StackPanel Name="sp">
    </StackPanel>
</Window>

XAML.CS، لصق أقل من الدفاءة الافتراضية:

namespace wpfBug
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Image i = new Image();
            BitmapImage src = new BitmapImage();
            src.BeginInit();
            src.UriSource = new Uri("picture.jpg", UriKind.Relative);
            src.EndInit();
            i.Source = src;
            i.Stretch = Stretch.Uniform;
            //int q = src.PixelHeight;        // Image loads here
            sp.Children.Add(i);
        }
    }
}

انسخ صورة إلى مجلد BIN / Debug واستدعاءها "picture.jpg"

هذا البرنامج لا يعرض أي شيء، ما لم يكن الخط المعلق غير مألوف.

هل يمكن لأي شخص أن يفسر ما أفعله خطأ، أو لماذا يحدث هذا؟ إذا قمت بإزالة الصورة وتشغيل البرنامج، فإنه ينشئ سطر "INT Q = ...". إذا تم تعليق هذا الخط يعمل البرنامج دون استثناءات حتى لو لم يكن هناك صورة موجودة. قم بتحميل صورة فقط إذا كانت Nessesary منطقية، ولكن بعد ذلك، يجب تحميل الصورة عند إضافة عنصر تحكم الصورة إلى StackPanel.

أي معلمين؟

تحرير: بالمناسبة، إذا قمت بإضافة الصورة كمورد، فلن تكون هناك حاجة إلى "INT Q = ..".

هل كانت مفيدة؟

المحلول

ذلك لأن الإبداع قد تأخر. إذا كنت تريد تحميل الصورة على الفور، فيمكنك ببساطة إضافة هذا التعليمات البرمجية إلى مرحلة INIT.

src.cachooption = bitmapcachoodtion.Onload؛

مثله:

src.BeginInit();
src.UriSource = new Uri("picture.jpg", UriKind.Relative);
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();

نصائح أخرى

في التعليمات البرمجية لتحميل المورد في التجميع المنفذ حيث كان صورتي "freq.png" في مجلد "الرموز" وحددها ك "مورد".

        this.Icon = new BitmapImage(new Uri(@"pack://application:,,,/" 
             + Assembly.GetExecutingAssembly().GetName().Name 
             + ";component/" 
             + "Icons/Freq.png", UriKind.Absolute)); 

أنا أيضا عملت وظيفة إذا كان أي شخص يرغب في ذلك ...

/// <summary>
/// Load a resource WPF-BitmapImage (png, bmp, ...) from embedded resource defined as 'Resource' not as 'Embedded resource'.
/// </summary>
/// <param name="pathInApplication">Path without starting slash</param>
/// <param name="assembly">Usually 'Assembly.GetExecutingAssembly()'. If not mentionned, I will use the calling assembly</param>
/// <returns></returns>
public static BitmapImage LoadBitmapFromResource(string pathInApplication, Assembly assembly = null)
{
    if (assembly == null)
    {
        assembly = Assembly.GetCallingAssembly();
    }

    if (pathInApplication[0] == '/')
    {
        pathInApplication = pathInApplication.Substring(1);
    }
    return new BitmapImage(new Uri(@"pack://application:,,,/" + assembly.GetName().Name + ";component/" + pathInApplication, UriKind.Absolute)); 
}

الاستعمال:

        this.Icon = ResourceHelper.LoadBitmapFromResource("Icons/Freq.png");

هذا سلوك غريب وعلى الرغم من أنني غير قادر على القول لماذا يحدث هذا، يمكنني أن أوصي ببعض الخيارات.

أولا، ملاحظة. إذا قمت بتضمين الصورة كحتوى في VS ونسخه إلى دليل الإخراج، يعمل التعليمات البرمجية الخاصة بك. إذا تم وضع علامة على الصورة أي لا شيء في مقابل ونسخها، فلا تعمل.

الحل 1: FileStream

يقبل كائن BitMapImage تحليل أو StreamSource كمعلمة. دعونا نستخدم StreamSource بدلا من ذلك.

        FileStream stream = new FileStream("picture.png", FileMode.Open, FileAccess.Read);
        Image i = new Image();
        BitmapImage src = new BitmapImage();
        src.BeginInit();
        src.StreamSource = stream;
        src.EndInit();
        i.Source = src;
        i.Stretch = Stretch.Uniform;
        panel.Children.Add(i);

المشكلة: يبقى دفق مفتوحا. إذا قمت بإغلاقه في نهاية هذه الطريقة، فلن تظهر الصورة. هذا يعني أن الملف يبقى مغلقا على النظام.

الحل 2: مخصص

هذا هو الحل أساسا 1 ولكن عليك قراءة الملف في دفق الذاكرة وتمرير مجرى الذاكرة كوسيطة.

        MemoryStream ms = new MemoryStream();
        FileStream stream = new FileStream("picture.png", FileMode.Open, FileAccess.Read);
        ms.SetLength(stream.Length);
        stream.Read(ms.GetBuffer(), 0, (int)stream.Length);

        ms.Flush();
        stream.Close();

        Image i = new Image();
        BitmapImage src = new BitmapImage();
        src.BeginInit();
        src.StreamSource = ms;
        src.EndInit();
        i.Source = src;
        i.Stretch = Stretch.Uniform;
        panel.Children.Add(i);

الآن أنت قادر على تعديل الملف على النظام، إذا كان هذا شيء تحتاج إليه.

يمكنك تجربة ربط المعالجات بأحداث مختلفة من BitmapImage:

قد يخبرونك قليلا حول ما يجري، بقدر ما يتعلق الأمر بالصورة.

فيما يلي طريقة التمديد لتحميل صورة من URI:

public static BitmapImage GetBitmapImage(
    this Uri imageAbsolutePath,
    BitmapCacheOption bitmapCacheOption = BitmapCacheOption.Default)
{
    BitmapImage image = new BitmapImage();
    image.BeginInit();
    image.CacheOption = bitmapCacheOption;
    image.UriSource = imageAbsolutePath;
    image.EndInit();

    return image;
}

عينة من الاستخدام:

Uri _imageUri = new Uri(imageAbsolutePath);
ImageXamlElement.Source = _imageUri.GetBitmapImage(BitmapCacheOption.OnLoad);

سهل هكذا!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top