WPF MVVM应用如何自动扫描视图生成侧边栏按钮实现动态视图切换
第一步:定义视图元数据类
首先新建一个简单的类用来存储每个视图要绑定的信息,避免直接绑定Type带来的处理麻烦:
public class ViewMetadata { // 按钮显示的名称(去掉View后缀) public string DisplayName { get; set; } // 命令需要传入的视图类名 public string ViewName { get; set; } }
第二步:反射生成视图集合
在你的主ViewModel里构造ViewsCollection,类型为ObservableCollection<ViewMetadata>,扫描指定命名空间下的所有符合规则的视图:
// 主ViewModel里的属性 public ObservableCollection<ViewMetadata> ViewsCollection { get; set; } = new(); // 初始化时执行扫描逻辑 void LoadAllViews() { // 指定你的视图所在的程序集,这里默认取当前程序集,跨程序集请自行调整 var assembly = Assembly.GetExecutingAssembly(); // 过滤出指定命名空间下、名称以View结尾、继承自FrameworkElement的类 var viewTypes = assembly.GetTypes() .Where(t => t.Namespace == "Program.Views" && t.Name.EndsWith("View") && typeof(FrameworkElement).IsAssignableFrom(t)); foreach (var viewType in viewTypes) { ViewsCollection.Add(new ViewMetadata { // 去掉末尾的View后缀作为显示名 DisplayName = viewType.Name[0..^4], ViewName = viewType.Name }); } }
第三步:修改XAML绑定逻辑
因为ItemsControl的ItemTemplate的DataContext是单个ViewMetadata对象,所以要通过RelativeSource找到主ViewModel的命令,同时绑定对应属性:
<ItemsControl ItemsSource="{Binding ViewsCollection}"> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Button Content="{Binding DisplayName}" Command="{Binding DataContext.ChangeViewCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" CommandParameter="{Binding ViewName}" HorizontalAlignment="Center" VerticalAlignment="Center" Height="40"/> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
补充注意事项
- 你的
CurrentControlView属性需要实现INotifyPropertyChanged通知,否则赋值后界面不会自动刷新 - 如果后续需要自定义按钮显示名(比如中文),可以给视图类加自定义Attribute,扫描时读取Attribute值作为DisplayName即可
- 如果你的视图放在单独的类库中,需要调整反射时获取程序集的逻辑
内容的提问来源于stack exchange,提问作者mummy
相关产品推荐
相关产品推荐

