【发布时间】:2021-07-01 13:41:00
【问题描述】:
在我的 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 的内容?
编辑:每次用户想要通过按钮加载新图像时都应该这样做,而不仅仅是在初始化期间。
编辑:
使用 lidqy 和 EldHasp 的 cmets,我能够使用 ObservableCollection 和 ItemsControl 清理 VM 和视图。
虚拟机
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>
非常整洁。
【问题讨论】:
-
尝试在 ViewModel1 构造函数中调用
LoadImages()。 -
请注意,您不应该在视图模型中使用 BitmapImage 类型。相反,请使用基类 ImageSource,或者如果您确实需要访问特定于位图的属性,请使用 BitmapSource。
-
除此之外,ContentChanged 事件背后的魔法是什么?它曾经被任何组件订阅过吗?不应该有类似
OnPropertyChanged(nameof(Images))的东西吗? -
@LeiYang 是的,这有效,但在初始化期间只有一次。我澄清了我的问题。
-
另请注意,UpdateSourceTrigger=PropertyChanged 和 Mode=TwoWay 对 Image 元素的 Source Binding 毫无意义。