【问题标题】:How to reload an image in XAML?如何在 XAML 中重新加载图像?
【发布时间】:2018-08-20 17:19:23
【问题描述】:

我正在编写一个 UWP。在这个应用程序的界面中,按钮下有一个 Image 和一个绑定到图像集合的 ObservableCollection。

<Image VerticalAlignment="Center"
    HorizontalAlignment="Center" Stretch="Fill"
    x:Name="FlatWallpaperUI"/>

但是,这些图像在选择某种重音颜色时会进行处理并变化。 例如,当应用程序启动时,图像会以正确的颜色加载:

我正在尝试通过重置 ObservableCollection 或将 Bitmapimage 重新分配给 XAML 中的图像来重新加载这些图像。 例如,我将位图图像重新分配给按钮下的图像:

ButtonImage.Source = new BitmapImage(new Uri("ms-appx:///Assets/wallpaper2.png"));

对于 ObservableCollection,我尝试清空它,然后阅读这些项目:

Items.Clear();
Items.Add(new ItemClass
  {
    Name = "First item",
    Image = new BitmapImage(new Uri("ms-appx:///Assets/wallpaper1.png"))
  });
Items.Add(new ItemClass
  {
    Name = "Second item",
    Image = new BitmapImage(new Uri("ms-appx:///Assets/wallpaper2.png"))
  });

我知道这可能是错误的方法,但我已经研究了一段时间,到目前为止还没有明确的解决方案。

在这张图片上,您会看到颜色发生了变化,但图片本身没有!

即使应该处理的图像本身已经成功更改!

我怎样才能解决这个问题并在需要时更新图像?

【问题讨论】:

  • 如果您能提供minimal reproducible example,那就太好了。
  • “我正在尝试通过重置 ObservableCollection 或将 Bitmapimage 重新分配给 XAML 中的图像来重新加载这些图像。” - 为使答案完整,请包含执行这些操作的代码。跨度>
  • 我很抱歉这个问题不清楚......我重新分配位图图像的意思是我再次将图像源设置为相同的图像,希望它将重新加载到界面中。我已将此添加到问题中。
  • 你只有一个图像控件,为什么要使用ObservableCollection
  • 我无法从上面的描述中找出您的要求,可以分享更多代码,例如您的 xaml 绑定设计或提供一个简单的示例。

标签: c# image xaml uwp


【解决方案1】:

首先:我同意您可以共享更多代码。图片不错,但对解决您的问题没有太大帮助。

第二:我的猜测是您假设更改 ObservableCollection 元素的属性将触发更新,但事实并非如此。如果我在这里是一个可能的解决方案,如果我的猜测不好,请编辑您的问题并澄清:

你可以像这样创建自己的 ObservableCollection 并监听一些元素的修改:

public class ModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged(String PropName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(PropName));
        }
    }

    protected void SetAndRaisePropertyChanged<T>(ref T Prop, T value, [CallerMemberName] String PropName = "")
    {
        Prop = value;
        RaisePropertyChanged(PropName);
    }
}

public class CustomCollection<T> : ObservableCollection<T> where T : ModelBase
{
    public event PropertyChangedEventHandler ChildrenPropertyChanged;
    protected override void ClearItems()
    {
        base.ClearItems();

        foreach (var item in this)
        {
            DisposeItem(item);
        }
    }

    protected override void InsertItem(int index, T item)
    {
        base.InsertItem(index, item);
        item.PropertyChanged += Model_PropertyChanged;
    }

    protected override void RemoveItem(int index)
    {
        base.RemoveItem(index);
        DisposeItem(this[index]);
    }

    private void DisposeItem(ModelBase model)
    {
        model.PropertyChanged -= Model_PropertyChanged;
    }

    private void Model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        ChildrenPropertyChanged.Invoke(sender, e);
    }
}

然后在你的代码中你可以这样听:

private CustomCollection<ItemClass> m_Items = new CustomCollection<ItemClass>();
public CustomCollection<ItemClass> Items
{
    get { return m_Items; }
    set => SetAndRaisePropertyChanged(ref m_Items, value);
}

[...]

Items.ChildrenPropertyChanged += Items_ChildrenPropertyChanged;

[...]

private void Items_ChildrenPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    [...] // here you force the refresh by raising the property changed for example
}

【讨论】:

  • 这是一个好的开始。很抱歉,我不清楚这个问题以及其中缺少代码。问题是我不知道如何从代码开始。这个想法是将可观察集合(BitmabImage 的集合)绑定到 UI。这些图像在一个文件夹中。该应用程序会更改这些图像上的颜色。但是除非我重新启动应用程序,否则这些更改不会出现在 UI 中 - 从源重新加载图像。 (observableCollection Items 是一样的,只是图像会发生颜色变化)在这种情况下,使用PropertyChangedEventArgs 可能会起作用。
  • 好吧,只是为了确定,(因为它可能取决于图像的数量)你真的需要把它们放在一个 observableCollection 中吗?它们可能是单个属性,可以避免我发布的所有机制。如果出于某种原因您认为以这种方式处理它们更容易,我认为我的代码可能会有所帮助。在任何情况下,如果您仍然有更新问题,您可以手动调用您知道已修改的图像的 RaisePropertyChanged 方法,至少尝试一下。
猜你喜欢
  • 1970-01-01
  • 2017-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
  • 1970-01-01
  • 2014-01-08
  • 2011-01-07
相关资源
最近更新 更多