当前位置: 首页 > news >正文

Wpf学习片段

IRegionManager 和IContainerExtension

IRegionManager 是 Prism 框架中用于管理 UI 区域(Regions)的核心接口,它实现了模块化应用中视图(Views)的动态加载、导航和生命周期管理。

IContainerExtension 是依赖注入(DI)容器的抽象接口,而 Resolve<T>() 方法用于从容器中解析指定类型的实例

 
public class u1: UserControl
{IRegionManager _regionManager;IContainerExtension _container;public u1(IContainerExtension container, IRegionManager regionManager){_regionManager = regionManager;_container = container;//从容器中解析ListView类型的实例。如果ListView已注册为单例,则返回单例实例;否则返回新实例ListView ListView11 =_container.Resolve<ListView>();//获取中心显示区域IRegion region= _regionManager.Regions["ContentRegion"];//为中心显示区域添加视图(ListView11),并为视图分配一个名称“ListView1”region.Add(ListView11 , "ListView1");//将指定视图(ListView11)设置为区域(region)中的活动视图region.Activate(ListView11);}}

u1的xaml中有:

<ContentControl Grid.Column="1" prism:RegionManager.RegionName="ContentRegion" />

......

<dx:DXTabItem Header="名称">
       <local:ListView/>//将 ListView 视图嵌入到 DXTabItem 中,作为选项卡页的内容。

</dx:DXTabItem>

其中ListView是自定义的另一个用户控件。

在 Prism 框架中,结合第三方控件库(如 DevExpress 的 DXTabItem)时,可以通过 XAML 直接定义视图(如 ListView)并将其嵌入到选项卡控件中。

region.Activate(view) 方法用于将指定视图(view)设置为区域(IRegion)中的活动视图。

单选框的动态绑定

  <StackPanel Margin="20">
            <TextBlock Text="组合单选框" FontWeight="Bold"/>
            <DockPanel x:Name="GroupRadioButton">
                <StackPanel DockPanel.Dock="Left">
                    <ItemsControl ItemsSource="{Binding RadioButtons}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <RadioButton Content="{Binding SecurityId}" 
                                     IsChecked="{Binding IsSelected, Mode=TwoWay}"
                                     GroupName="RadioButtons"
                                     Command="{Binding DataContext.RadioCheckCommand, 
                                     RelativeSource={RelativeSource AncestorType=Window}}"
                                     CommandParameter="{Binding}">
                                </RadioButton>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </StackPanel>

                <StackPanel DockPanel.Dock="Right" 
                    Orientation="Horizontal" 
                    HorizontalAlignment="Center" 
                    VerticalAlignment="Center">
                    <TextBlock Text="{Binding SelectedRadioButton.SecurityId, StringFormat='结果:{0}'}" />
                </StackPanel>
            </DockPanel>
        </StackPanel>

using Prism.Commands;
using Prism.Mvvm;
using StrategyClient.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;namespace StrategyClient.ViewModels
{class SellStrategyViewModel : BindableBase{/// <summary>/// 当前选择的单选框/// </summary>private ConfigAccount _selectedRadioButton;/// <summary>/// 当前选择的单选框/// </summary>public ConfigAccount SelectedRadioButton{get => _selectedRadioButton;set => SetProperty(ref _selectedRadioButton, value);}/// <summary>/// 需要显示的一组单选框的信息链表/// </summary>public ObservableCollection<ConfigAccount> RadioButtons { get; } = new ObservableCollection<ConfigAccount>();/// <summary>/// 绑定命令触发(单选框选择改变时)/// </summary>public DelegateCommand<ConfigAccount> RadioCheckCommand { get; }public SellStrategyViewModel(){// 初始化单选框选项RadioButtons.Add(new ConfigAccount { SecurityId = "选项1", IsSelected = false });RadioButtons.Add(new ConfigAccount { SecurityId = "选项2", IsSelected = false });RadioButtons.Add(new ConfigAccount { SecurityId = "选项3", IsSelected = false });// 设置默认选中项if (RadioButtons.Count > 0){RadioButtons[0].IsSelected = true;SelectedRadioButton = RadioButtons[0];}// 注册命令RadioCheckCommand = new DelegateCommand<ConfigAccount>(OnRadioChecked);}private void OnRadioChecked(ConfigAccount item){// 更新选中项foreach (var radioButton in RadioButtons){radioButton.IsSelected = radioButton == item;}SelectedRadioButton = item;}}
}

检查UI绑定路径

xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"

......

<CheckBox IsChecked="{Binding IsSelectedV, Mode=TwoWay, diagnostics:PresentationTraceSources.TraceLevel=High}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>

如果直接绑定到 IsSelectedV 属性不起作用,可以尝试使用 CellValue 绑定:

<CheckBox IsChecked="{Binding RowData.Row.IsSelectedV, Mode=TwoWay}"/>

在这种情况下,RowData.Row 通常是指当前行的数据对象。

实现弹窗功能:

 //App中注册对话框
containerRegistry.RegisterDialog<View, ViewModel>();

// 显示弹窗
void ShowDialog(string name, IDialogParameters parameters, Action<IDialogResult> callback);
 
// 显示模态弹窗(阻塞式)
void Show(string name, IDialogParameters parameters, Action<IDialogResult> callback);

 主视图的ViewModel:

public ObservableCollection<string> Items
{
            get;
            set;
 } = new ObservableCollection<string>();

       /// <summary>
        /// 按钮按下弹窗
        /// </summary>
        private void Button_Click()
        {
            //传递参数
            var parameters = new DialogParameters
                {
                    { "DataList", Items }
                };

                //View:视图名,parameters:要传递的参数

            _dialogService.ShowDialog("View", parameters, (IDialogResult result) =>
            {//弹窗关闭后回调函数
                // 从结果中获取数据链表
                if (result.Parameters.TryGetValue<ObservableCollection<string>>("DataList", out var dataList))
                {
                    Items = dataList;
                }
            });

        }

 // 定义弹窗事件
public class ShowDialogEvent : PubSubEvent<DialogParameters> { }

// 发布弹窗请求
var parameters = new DialogParameters { { "message", "保存成功!" } };
_eventAggregator.GetEvent<ShowDialogEvent>().Publish(parameters);
 
// 弹窗服务订阅事件并显示弹窗
_eventAggregator.GetEvent<ShowDialogEvent>()
    .Subscribe(ShowDialog, ThreadOption.UIThread);
private void ShowDialog(DialogParameters parameters)
{
    _dialogService.ShowDialog("MessageDialog", parameters);
}

View视图的ViewModel

class ViewModel : BindableBase, IDialogAware

{

public ObservableCollection<string> Items
{
           get => _items;
            set => SetProperty(ref _items, value);
 }

 /// <summary>
        /// 对话框事件,传递对话框的结果
        /// </summary>
        public event Action<IDialogResult> RequestClose;
        /// <summary>
        /// 关闭对话框时传递参数
        /// </summary>
        public event Action<IDialogParameters> RequestClosed;

  // 对话框标题
        public string Title => "弹窗标题";

  /// <summary>
        /// 允许关闭对话框
        /// </summary>
        /// <returns></returns>
        public bool CanCloseDialog()
        {
            return true;
        }

        /// <summary>
        /// 关闭对话框时
        /// </summary>
        public void OnDialogClosed()
        {
            var resultParameters = new DialogParameters
            {
                { "DataList", Items }
            };
            // 触发请求关闭事件
            RequestClosed?.Invoke(resultParameters);
        }

        /// <summary>
        /// 打开对话框时
        /// </summary>
        /// <param name="parameters"></param>
        public void OnDialogOpened(IDialogParameters parameters)
        {
            if (parameters.TryGetValue<ObservableCollection<SellStrategyModel>>("DataList", out var initialName))
            {
                Items = initialName;
            }
        }

}

单选框:

<DockPanel x:Name="GroupRadioButton">
                    <ItemsControl ItemsSource="{Binding RadioButtons}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <WrapPanel Orientation="Horizontal"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <RadioButton Content="{Binding Id}" 
                                     IsChecked="{Binding IsSelected, Mode=TwoWay}"
                                     GroupName="RadioButtons"
                                     Command="{Binding DataContext.RadioCheckCommand, 
                                     RelativeSource={RelativeSource AncestorType=Window}}"
                                     CommandParameter="{Binding}">
                                </RadioButton>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </DockPanel>

viewModel

 /// <summary>
        /// 当前选择的单选框
        /// </summary>
        private ConfigAccount _selectedRadioButton;
        /// <summary>
        /// 当前选择的单选框
        /// </summary>
        public ConfigAccount SelectedRadioButton
        {
            get => _selectedRadioButton;
            set => SetProperty(ref _selectedRadioButton, value);
        }

 /// <summary>
        /// 需要显示的一组单选框的信息链表
        /// </summary>
        public ObservableCollection<ConfigAccount> RadioButtons { get; } = new ObservableCollection<ConfigAccount>();
        /// <summary>
        /// 绑定命令触发(单选框选择改变时)
        /// </summary>
        public DelegateCommand<ConfigAccount> RadioCheckCommand { get; }

         public ViewModel()
        {
            AddSecurityStrategy();
            // 设置默认选中项
            if (RadioButtons.Count > 0)
            {
                RadioButtons[0].IsSelected = true;
                SelectedRadioButton = RadioButtons[0];
            }
            RadioCheckCommand = new DelegateCommand<ConfigAccount>(OnRadioChecked);
        }

 /// <summary>
        /// 单选框按钮选择时触发
        /// </summary>
        /// <param name="item">选择的单选框对象</param>
        private void OnRadioChecked(ConfigAccount item)
        {
            // 更新选中项
            //foreach (var radioButton in RadioButtons)
            //{
            //    radioButton.IsSelected = radioButton == item;
            //}
            SelectedRadioButton = item;
        }

        /// <summary>
        /// 添加需要显示的单选框按钮
        /// </summary>
        private void AddSecurityStrategy()
        {
            string[] addStrategys = System.Configuration.ConfigurationManager.AppSettings["SellStrategy"].ToString().Split('|');
            foreach (string addStrategy in addStrategys)
            {
                RadioButtons.Add(new ConfigAccount() { IsSelected = false, SecurityId = addStrategy });
            }
        }
 

动态加载不同模块的 UI

方法一:

1.注册区域
确保 "MainContent" 区域已通过 IRegionManager 注册(通常在 XAML 中声明或代码中动态添加):

_regionManager.Regions.Add("MainContent", new Region());

或者

<!-- 或在 XAML 中声明区域 --> <ContentControl prism:RegionManager.RegionName="MainContent" />

2.App.xaml.cs

 //MainView:要加载的视图的名称,MainView1:起的名字

containerRegistry.RegisterForNavigation<MainWindowView, MainWindowViewModel>("MainView1");

//MainView:要加载的视图的名称,没起名字

registry.RegisterForNavigation<MainWindowView, MainWindowViewModel>();

3.点击按钮时实现ViewModel:

//起名字了这里传入起的名字

_regionManager.RequestNavigate("MainContent", "MainView1");

//没起名字,这里传入类名

_regionManager.RequestNavigate("MainContent", "MainWindowView");

//传递参数:

var parameters = new NavigationParameters();

parameters.Add("orderId", 123);

_regionManager.RequestNavigate("MainRegion", "OrderDetailView", parameters);

方法二:

1.注册区域
确保 "MainContent" 区域已通过 IRegionManager 注册(通常在 XAML 中声明或代码中动态添加):

_regionManager.Regions.Add("MainContent", new Region());

或者

<!-- 或在 XAML 中声明区域 --> <ContentControl prism:RegionManager.RegionName="MainContent" />

2.在模块初始化时注册视图到指定区域:

void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {//开始的时候MainContent会显示loading视图
            _regionManager.RegisterViewWithRegion("MainContent", typeof(loading));
        }

3.点击按钮时实现ViewModel:

   _regionManager.RequestNavigate("MainContent", "loading");

获取UI界面实例的view Model,调用对应的函数

方法一:

  // 获取目标区域
IRegion contentRegion = _regionManager.Regions["MainContent"];
// 获取当前激活的视图
object activeView = contentRegion.ActiveViews.FirstOrDefault();
 // 获取视图的 DataContext(即 ViewModel)
var viewModel = activeView.GetType().GetProperty("DataContext")?.GetValue(activeView) as DownLoadViewModel;
 //调用视图方法改变UI内文字
viewModel?.testc();

方法二:

//注册为单例

registry.RegisterSingleton<DownLoadViewModel>();

// 直接解析 ViewModel 实例
var viewMode2 = _container.Resolve<DownLoadViewModel>();
viewMode2?.testc();

注册服务

方法用途生命周期控制
RegisterForNavigation<TView>()注册视图到导航系统,自动绑定 ViewModel(通过命名约定)默认瞬态(每次导航创建新实例)
RegisterSingleton<T>()注册类型为单例,全局唯一实例单例
RegisterForNavigation<TView, TViewModel>()显式指定视图和 ViewModel 的绑定关系可自定义(结合其他注册方法)
Register<TInterface, TImplementation>()注册接口到具体实现默认瞬态
RegisterInstance<T>(T instance)注册已创建的实例为单例单例

//举例

registry.RegisterForNavigation<DownLoadView, DownLoadViewModel>("DownLoad1");
registry.RegisterForNavigation<MainWindowView, MainWindowViewModel>();
 

registry.RegisterSingleton<DownLoadViewModel>();
 

registry.RegisterForNavigation<DownLoadView>("downLoad");
registry.RegisterForNavigation<loading>();

containerRegistry.Register<IDownLoadService, DownLoadService>();


var downloadService = new DownLoadService(); containerRegistry.RegisterInstance<IDownLoadService>(downloadService);

管理区域和视图:

方法用途特点
RegisterViewWithRegion静态注册视图到区域,自动加载适用于固定视图,初始化时自动加载
RequestNavigate动态导航到视图,支持参数和回调适用于按需加载的视图,支持导航逻辑
IRegion.Add / IRegion.Remove手动添加或移除视图适用于精细控制视图的显示/隐藏
IRegion.Activate / IRegion.Deactivate激活或停用视图适用于切换视图的可见性
IRegion.NavigationService通过导航服务实现复杂导航逻辑适用于需要自定义导航流程的场景

//举例

protected override void OnInitialized(IContainerProvider containerProvider)

{

var regionManager = containerProvider.Resolve<IRegionManager>();

// 将 OrderListView 注册到 MainRegion,视图会在区域初始化时自动加载 regionManager.RegisterViewWithRegion("MainRegion", typeof(OrderListView));

}
 

_regionManager.RequestNavigate("MainContent", "loading");


var region = _regionManager.Regions["MainRegion"];

var view = _container.Resolve<OrderListView>();

region.Add(view); region.Activate(view); // 激活视图


var region = _regionManager.Regions["MainRegion"];

var view = region.Views.FirstOrDefault(v => v is OrderListView); if (view != null)

{ region.Remove(view); }


var region = _regionManager.Regions["MainRegion"];

var view = region.Views.FirstOrDefault(v => v is OrderListView); if (view != null)

{

region.Activate(view); // 激活视图

// region.Deactivate(view); // 停用视图

}

INavigationAware:

INavigationAware 是 Prism 框架中用于处理导航生命周期事件的核心接口。它允许 ViewModel 在导航过程中响应以下三个关键事件:

  • 导航到当前视图时(OnNavigatedTo
  • 从当前视图导航离开时(OnNavigatedFrom
  • 导航确认阶段(IsNavigationTarget,用于决定是否复用现有 ViewModel 实例)

通过实现 INavigationAware,可以精细控制 ViewModel 在导航过程中的行为,例如初始化数据、清理资源或决定是否复用实例。

  • INavigationAware 是 Prism 中管理导航生命周期的核心接口。
  • 通过实现 IsNavigationTargetOnNavigatedTo 和 OnNavigatedFrom,可以精细控制 ViewModel 在导航过程中的行为。
  • 适用于需要初始化数据、清理资源或决定是否复用实例的场景。
  • 合理使用导航参数(NavigationParameters)可以传递上下文数据。

区域上下文 

是一种用于在区域(IRegion)和其宿主控件(如 ContentControlItemsControl 等)之间传递上下文数据的机制。它允许开发者在区域中共享数据,而无需直接依赖视图或视图模型,从而提升代码的解耦性和灵活性。

// 获取区域并设置上下文 var region = _regionManager.Regions["MainRegion"]; region.Context = new AppContext { UserId = "123", Role = "Admin" };//AppContext:自定义Mode

相关文章:

  • 从海洋生物找灵感:造个机器人RoboPteropod,它能在水下干啥?
  • 当生产了~/qt-arm/bin/qmake,可以单独编译其他-源码的某个模块,如下,编译/qtmultimedia
  • Hadoop区别
  • ElasticSearch聚合操作案例
  • 基于MCP的智能体架构设计:实现智能体与外部世界的无缝连接
  • 【NextPilot日志移植】ULog
  • 【免费】2005-2018年各省人均财政收支数据
  • HTTPS全解析:从证书签发到TLS握手优化
  • Qt for Android申请允许管理所有文件权限
  • [网络层]网络层设备路由器
  • 使用基于ARM的低功耗微型单板计算机打造智能家居管理系统中枢
  • 如何应对网站被爬虫和采集?综合防护策略与实用方案
  • ZYNQ处理器在发热后功耗增加的原因分析及解决方案
  • PDM采集数字麦克风数据
  • nvm管理node版本
  • 安卓玩机工具-----安卓机型一款很好用的数据备份恢复软件 支持云端备份
  • Qt创建项目
  • vue+threeJS 大理石贴图
  • WEB安全--RCE--webshell bypass2
  • Dagster Pipes系列-2:增强外部脚本与Dagster的交互能力
  • 人民网评:守护健康证的“健康”,才有舌尖上的安全
  • 从600名外到跻身大满贯,孙发京:走过的路成就了现在的我
  • 白玉兰奖征片综述丨综艺市场破局焕新,多元赛道重塑价值坐标
  • 打击网络谣言、共建清朗家园,中国互联网联合辟谣平台2025年4月辟谣榜
  • 前四月全国铁路完成固定资产投资1947亿元,同比增长5.3%
  • 卢正已任上海市司法局党委委员、副局长