Wpf学习片段

IRegionManagerIContainerExtension

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

区域上下文

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

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

App.config用法

App.config代码:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<startup>

<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />

</startup>

<appSettings>

<add key="keyName" value="valueName"/>

<add key="keyName2" value="valueName2"/>

<add key="keyName3" value="valueName3"/>

</appSettings>

</configuration>
string settingValue = System.Configuration.ConfigurationManager.AppSettings["keyName"];

相关推荐
虾球xz1 小时前
CppCon 2016 学习:The Exception Situation
开发语言·c++·学习
蒙奇D索大1 小时前
【数据结构】图论实战:DAG空间压缩术——42%存储优化实战解析
数据结构·笔记·学习·考研·图论·改行学it
ᥬ 小月亮1 小时前
Mongodb下载安装与使用(Windows版本)
windows·学习·mongodb
今天我要乾重生1 小时前
java基础学习(三十)
java·开发语言·学习
西岭千秋雪_2 小时前
计算机网络学习笔记:TCP流控、拥塞控制
网络·笔记·学习·tcp/ip·计算机网络
梦境虽美,却不长4 小时前
C++ 学习 多线程 2025年6月17日18:41:30
c++·学习·线程·异步
电院工程师5 小时前
2.4 Python基础概念:通过一个文字冒险游戏学习编程
开发语言·python·学习·算法·游戏·游戏程序
大苏打seven5 小时前
Docker学习笔记:数据卷
笔记·学习·docker
霖霖7147 小时前
linux系统驱动的原理
linux·笔记·学习
虾球xz7 小时前
CppCon 2016 学习:Parallelism in Modern C++
开发语言·c++·学习