首页 > 解决方案 > 更改源后 WPF 图像显示未更新

问题描述

在我的 MainView 中有一个 ContentControl 绑定到 CurrentView 对象。CurrentView 通过绑定到命令的 MainView 上的按钮进行更改。

主视图

<Window>(...)
       <RadioButton Content="View1"
                    Command="{Binding View1Command}"/>
       <RadioButton Content="View2" 
                    Command="{Binding View2Command}"/>
   <ContentControl Content="{Binding CurrentView}"/>
</Window>

主虚拟机

(ObservableObject 类实现 INotifyPropertyChanged 和 RelayCommand 类 ICommand。)

class MainViewModel : ObservableObject
{
        public RelayCommand ViewCommand1 { get; set; }
        public RelayCommand ViewCommand2 { get; set; }

        public ViewModel2 VM1 { get; set; }
        public ViewModel2 VM2 { get; set; }
        
        object _currentView;
        
        public object CurrentView
        {
            get { return _currentView; }
            set 
            { 
                _currentView = value;
                OnPropertyChanged();
            }
        }
    public MainViewModel()
    {
      VM1 = new ViewModel1();
      VM1.ContentChanged += (s, e) => OnPropertyChanged();
      ViewCommand1 = new RelayCommand(o =>
            {
                CurrentView = VM1;
            });

      VM2 = new ViewModel2();
      ViewCommand2 = new RelayCommand(o =>
            {
                CurrentView = VM2;
            });
    }
 }

这些(子)VM 绑定到包含图像控件和从文件加载图像源的按钮的 UserControls。

视图1

<UserControl x:Class="Project.Views.View1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:viewModels="clr-namespace:Project.ViewModels" 
             d:DataContext="{d:DesignInstance Type=viewModels:ViewModel1}"
             mc:Ignorable="d" >
[...]
  <Button Command="{Binding LoadImagesCommand}"/>
[...]
  <Image Source="{Binding Images[0]}" "/>
  <Image Source="{Binding Images[1]}" "/>
[...]
</UserControl>

虚拟机1

class RiJustageViewModel: ObservableObject
{
    public event EventHandler ContentChanged;
    void OnContentChanged()
    {
        ContentChanged?.Invoke(this, new EventArgs());
    }

    public RelayCommand LoadImagesCommand { get; set; }
    
    public ViewModel1()
    {
        Images = new BitmapImage[9];
        LoadImagesCommand = new RelayCommand(o => LoadImages());
    }

    BitmapImage[] _images;

    public BitmapImage[] Images
    {
        get { return _images; }
        set
        {
            _images = value;
            OnContentChanged();
        }
    }

    public void LoadImages()
    {  
        [...]
        for (int i = 0; i < files.Length; i++)
        {
           Images[i] = Utility.BmImageFromFile(files[i]);
        }
        [...]
    }
}

现在的问题是图像在加载后不会立即显示。只有在我将 ContentControl 的内容更改为另一个视图然后返回 View1 之后,才会显示图像。

有没有办法在加载完成后立即触发该显示而不更改 ContentControl 的内容?

编辑:每次用户想要通过按钮加载新图像时都应该这样做,而不仅仅是在初始化期间。

ObservableCollection编辑:通过 lidqy 和 EldHasp 的评论,我能够使用and清理 VM 和视图ItemsControl

虚拟机

  public class ImageItem
    {
        public string FileName{ get; set; }
        public ImageSource Image { get; set; }
        public ImageItem(string f, ImageSource im)
        {
            FileName = f;
            Image = im;
        }
    }

    public ObservableCollection<ImageItem> ImageItems { get; set; }

   [...]
   public void LoadImages()
   {
     [...]
     ImageItems.Clear();
     foreach (var file in files)
     {
        var im = Utility.BmImageFromFile(file);
        var f = Path.GetFileName(file);
        ImageItems.Add(new ImageItem(f, im));
     }
}

看法

<ItemsControl ItemsSource="{Binding ImageItems}">
    <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
        <UniformGrid Columns="3" Rows="3"/>
      </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
            
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <Grid Margin="5">
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="400"/>
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
            <RowDefinition Height="18" />
            <RowDefinition Height="200" />
          </Grid.RowDefinitions>
          <TextBlock Text="{Binding FileName}" Style="{StaticResource ImageDescr}" />
          <Image Grid.Row="1" Source="{Binding Image}" Style="{StaticResource ImageTheme}" />
         </Grid>
       </DataTemplate>
     </ItemsControl.ItemTemplate>
  </ItemsControl>

井井有条。

标签: c#wpfxaml

解决方案


ContentChanged活动没用。

像这样声明Images属性:

private ImageSource[] images;

public ImageSource[] Images
{
    get { return images; }
    set
    {
        images = value;
        OnPropertyChanged();
    }
}

LoadImages()中,只需分配一个新数组:

public void LoadImages()
{
    ...  
    Images = files
        .Select(f => Utility.BmImageFromFile(f))
        .ToArray();
}

推荐阅读